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

Commit bc2de10d authored by Jeff Layton's avatar Jeff Layton Committed by Ilya Dryomov
Browse files

ceph: convert bools in ceph_mds_request to a new r_req_flags field



Currently, we have a bunch of bool flags in struct ceph_mds_request. We
need more flags though, but each bool takes (at least) a byte. Those
add up over time.

Merge all of the existing bools in this struct into a single unsigned
long, and use the set/test/clear_bit macros to manipulate them. These
are atomic operations, but that is required here to prevent
load/modify/store races. The existing flags are protected by different
locks, so we can't rely on them for that purpose.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Reviewed-by: default avatarYan, Zheng <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent f5a03b08
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -70,7 +70,7 @@ static int mdsc_show(struct seq_file *s, void *p)


		seq_printf(s, "%s", ceph_mds_op_name(req->r_op));
		seq_printf(s, "%s", ceph_mds_op_name(req->r_op));


		if (req->r_got_unsafe)
		if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags))
			seq_puts(s, "\t(unsafe)");
			seq_puts(s, "\t(unsafe)");
		else
		else
			seq_puts(s, "\t");
			seq_puts(s, "\t");
+2 −2
Original line number Original line Diff line number Diff line
@@ -371,7 +371,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
		/* hints to request -> mds selection code */
		/* hints to request -> mds selection code */
		req->r_direct_mode = USE_AUTH_MDS;
		req->r_direct_mode = USE_AUTH_MDS;
		req->r_direct_hash = ceph_frag_value(frag);
		req->r_direct_hash = ceph_frag_value(frag);
		req->r_direct_is_hash = true;
		__set_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags);
		if (fi->last_name) {
		if (fi->last_name) {
			req->r_path2 = kstrdup(fi->last_name, GFP_KERNEL);
			req->r_path2 = kstrdup(fi->last_name, GFP_KERNEL);
			if (!req->r_path2) {
			if (!req->r_path2) {
@@ -417,7 +417,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
		fi->frag = frag;
		fi->frag = frag;
		fi->last_readdir = req;
		fi->last_readdir = req;


		if (req->r_did_prepopulate) {
		if (test_bit(CEPH_MDS_R_DID_PREPOPULATE, &req->r_req_flags)) {
			fi->readdir_cache_idx = req->r_readdir_cache_idx;
			fi->readdir_cache_idx = req->r_readdir_cache_idx;
			if (fi->readdir_cache_idx < 0) {
			if (fi->readdir_cache_idx < 0) {
				/* preclude from marking dir ordered */
				/* preclude from marking dir ordered */
+9 −9
Original line number Original line Diff line number Diff line
@@ -1199,8 +1199,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)


		err = fill_inode(in, req->r_locked_page, &rinfo->targeti, NULL,
		err = fill_inode(in, req->r_locked_page, &rinfo->targeti, NULL,
				session, req->r_request_started,
				session, req->r_request_started,
				(!req->r_aborted && rinfo->head->result == 0) ?
				(!test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags) &&
				req->r_fmode : -1,
				rinfo->head->result == 0) ?  req->r_fmode : -1,
				&req->r_caps_reservation);
				&req->r_caps_reservation);
		if (err < 0) {
		if (err < 0) {
			pr_err("fill_inode badness %p %llx.%llx\n",
			pr_err("fill_inode badness %p %llx.%llx\n",
@@ -1213,8 +1213,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
	 * ignore null lease/binding on snapdir ENOENT, or else we
	 * ignore null lease/binding on snapdir ENOENT, or else we
	 * will have trouble splicing in the virtual snapdir later
	 * will have trouble splicing in the virtual snapdir later
	 */
	 */
	if (rinfo->head->is_dentry && !req->r_aborted &&
	if (rinfo->head->is_dentry && req->r_locked_dir &&
	    req->r_locked_dir &&
	    !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags) &&
	    (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name,
	    (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name,
					       fsc->mount_options->snapdir_name,
					       fsc->mount_options->snapdir_name,
					       req->r_dentry->d_name.len))) {
					       req->r_dentry->d_name.len))) {
@@ -1317,9 +1317,9 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
			update_dentry_lease(dn, rinfo->dlease, session,
			update_dentry_lease(dn, rinfo->dlease, session,
					    req->r_request_started);
					    req->r_request_started);
		dout(" final dn %p\n", dn);
		dout(" final dn %p\n", dn);
	} else if (!req->r_aborted &&
	} else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
		   (req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
		    req->r_op == CEPH_MDS_OP_MKSNAP) &&
		    req->r_op == CEPH_MDS_OP_MKSNAP)) {
		   !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
		struct dentry *dn = req->r_dentry;
		struct dentry *dn = req->r_dentry;
		struct inode *dir = req->r_locked_dir;
		struct inode *dir = req->r_locked_dir;


@@ -1444,7 +1444,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
	u32 fpos_offset;
	u32 fpos_offset;
	struct ceph_readdir_cache_control cache_ctl = {};
	struct ceph_readdir_cache_control cache_ctl = {};


	if (req->r_aborted)
	if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags))
		return readdir_prepopulate_inodes_only(req, session);
		return readdir_prepopulate_inodes_only(req, session);


	if (rinfo->hash_order && req->r_path2) {
	if (rinfo->hash_order && req->r_path2) {
@@ -1598,7 +1598,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
	}
	}
out:
out:
	if (err == 0 && skipped == 0) {
	if (err == 0 && skipped == 0) {
		req->r_did_prepopulate = true;
		set_bit(CEPH_MDS_R_DID_PREPOPULATE, &req->r_req_flags);
		req->r_readdir_cache_idx = cache_ctl.index;
		req->r_readdir_cache_idx = cache_ctl.index;
	}
	}
	ceph_readdir_cache_release(&cache_ctl);
	ceph_readdir_cache_release(&cache_ctl);
+25 −22
Original line number Original line Diff line number Diff line
@@ -644,13 +644,15 @@ static void __unregister_request(struct ceph_mds_client *mdsc,


	erase_request(&mdsc->request_tree, req);
	erase_request(&mdsc->request_tree, req);


	if (req->r_unsafe_dir && req->r_got_unsafe) {
	if (req->r_unsafe_dir  &&
	    test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
		struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir);
		struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir);
		spin_lock(&ci->i_unsafe_lock);
		spin_lock(&ci->i_unsafe_lock);
		list_del_init(&req->r_unsafe_dir_item);
		list_del_init(&req->r_unsafe_dir_item);
		spin_unlock(&ci->i_unsafe_lock);
		spin_unlock(&ci->i_unsafe_lock);
	}
	}
	if (req->r_target_inode && req->r_got_unsafe) {
	if (req->r_target_inode &&
	    test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
		struct ceph_inode_info *ci = ceph_inode(req->r_target_inode);
		struct ceph_inode_info *ci = ceph_inode(req->r_target_inode);
		spin_lock(&ci->i_unsafe_lock);
		spin_lock(&ci->i_unsafe_lock);
		list_del_init(&req->r_unsafe_target_item);
		list_del_init(&req->r_unsafe_target_item);
@@ -705,7 +707,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
	int mode = req->r_direct_mode;
	int mode = req->r_direct_mode;
	int mds = -1;
	int mds = -1;
	u32 hash = req->r_direct_hash;
	u32 hash = req->r_direct_hash;
	bool is_hash = req->r_direct_is_hash;
	bool is_hash = test_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags);


	/*
	/*
	 * is there a specific mds we should try?  ignore hint if we have
	 * is there a specific mds we should try?  ignore hint if we have
@@ -2042,7 +2044,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
	dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req,
	dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req,
	     req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts);
	     req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts);


	if (req->r_got_unsafe) {
	if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
		void *p;
		void *p;
		/*
		/*
		 * Replay.  Do not regenerate message (and rebuild
		 * Replay.  Do not regenerate message (and rebuild
@@ -2091,7 +2093,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,


	rhead = msg->front.iov_base;
	rhead = msg->front.iov_base;
	rhead->oldest_client_tid = cpu_to_le64(__get_oldest_tid(mdsc));
	rhead->oldest_client_tid = cpu_to_le64(__get_oldest_tid(mdsc));
	if (req->r_got_unsafe)
	if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags))
		flags |= CEPH_MDS_FLAG_REPLAY;
		flags |= CEPH_MDS_FLAG_REPLAY;
	if (req->r_locked_dir)
	if (req->r_locked_dir)
		flags |= CEPH_MDS_FLAG_WANT_DENTRY;
		flags |= CEPH_MDS_FLAG_WANT_DENTRY;
@@ -2114,8 +2116,8 @@ static int __do_request(struct ceph_mds_client *mdsc,
	int mds = -1;
	int mds = -1;
	int err = 0;
	int err = 0;


	if (req->r_err || req->r_got_result) {
	if (req->r_err || test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
		if (req->r_aborted)
		if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags))
			__unregister_request(mdsc, req);
			__unregister_request(mdsc, req);
		goto out;
		goto out;
	}
	}
@@ -2245,7 +2247,7 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds)
	while (p) {
	while (p) {
		req = rb_entry(p, struct ceph_mds_request, r_node);
		req = rb_entry(p, struct ceph_mds_request, r_node);
		p = rb_next(p);
		p = rb_next(p);
		if (req->r_got_unsafe)
		if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags))
			continue;
			continue;
		if (req->r_attempts > 0)
		if (req->r_attempts > 0)
			continue; /* only new requests */
			continue; /* only new requests */
@@ -2319,7 +2321,7 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
	mutex_lock(&mdsc->mutex);
	mutex_lock(&mdsc->mutex);


	/* only abort if we didn't race with a real reply */
	/* only abort if we didn't race with a real reply */
	if (req->r_got_result) {
	if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
		err = le32_to_cpu(req->r_reply_info.head->result);
		err = le32_to_cpu(req->r_reply_info.head->result);
	} else if (err < 0) {
	} else if (err < 0) {
		dout("aborted request %lld with %d\n", req->r_tid, err);
		dout("aborted request %lld with %d\n", req->r_tid, err);
@@ -2331,7 +2333,7 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
		 */
		 */
		mutex_lock(&req->r_fill_mutex);
		mutex_lock(&req->r_fill_mutex);
		req->r_err = err;
		req->r_err = err;
		req->r_aborted = true;
		set_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags);
		mutex_unlock(&req->r_fill_mutex);
		mutex_unlock(&req->r_fill_mutex);


		if (req->r_locked_dir &&
		if (req->r_locked_dir &&
@@ -2409,14 +2411,14 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
	}
	}


	/* dup? */
	/* dup? */
	if ((req->r_got_unsafe && !head->safe) ||
	if ((test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags) && !head->safe) ||
	    (req->r_got_safe && head->safe)) {
	    (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags) && head->safe)) {
		pr_warn("got a dup %s reply on %llu from mds%d\n",
		pr_warn("got a dup %s reply on %llu from mds%d\n",
			   head->safe ? "safe" : "unsafe", tid, mds);
			   head->safe ? "safe" : "unsafe", tid, mds);
		mutex_unlock(&mdsc->mutex);
		mutex_unlock(&mdsc->mutex);
		goto out;
		goto out;
	}
	}
	if (req->r_got_safe) {
	if (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags)) {
		pr_warn("got unsafe after safe on %llu from mds%d\n",
		pr_warn("got unsafe after safe on %llu from mds%d\n",
			   tid, mds);
			   tid, mds);
		mutex_unlock(&mdsc->mutex);
		mutex_unlock(&mdsc->mutex);
@@ -2455,10 +2457,10 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)




	if (head->safe) {
	if (head->safe) {
		req->r_got_safe = true;
		set_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags);
		__unregister_request(mdsc, req);
		__unregister_request(mdsc, req);


		if (req->r_got_unsafe) {
		if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
			/*
			/*
			 * We already handled the unsafe response, now do the
			 * We already handled the unsafe response, now do the
			 * cleanup.  No need to examine the response; the MDS
			 * cleanup.  No need to examine the response; the MDS
@@ -2476,7 +2478,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
			goto out;
			goto out;
		}
		}
	} else {
	} else {
		req->r_got_unsafe = true;
		set_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags);
		list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);
		list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);
		if (req->r_unsafe_dir) {
		if (req->r_unsafe_dir) {
			struct ceph_inode_info *ci =
			struct ceph_inode_info *ci =
@@ -2530,7 +2532,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
	if (realm)
	if (realm)
		ceph_put_snap_realm(mdsc, realm);
		ceph_put_snap_realm(mdsc, realm);


	if (err == 0 && req->r_got_unsafe && req->r_target_inode) {
	if (err == 0 && req->r_target_inode &&
	    test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
		struct ceph_inode_info *ci = ceph_inode(req->r_target_inode);
		struct ceph_inode_info *ci = ceph_inode(req->r_target_inode);
		spin_lock(&ci->i_unsafe_lock);
		spin_lock(&ci->i_unsafe_lock);
		list_add_tail(&req->r_unsafe_target_item, &ci->i_unsafe_iops);
		list_add_tail(&req->r_unsafe_target_item, &ci->i_unsafe_iops);
@@ -2538,12 +2541,12 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
	}
	}
out_err:
out_err:
	mutex_lock(&mdsc->mutex);
	mutex_lock(&mdsc->mutex);
	if (!req->r_aborted) {
	if (!test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
		if (err) {
		if (err) {
			req->r_err = err;
			req->r_err = err;
		} else {
		} else {
			req->r_reply =  ceph_msg_get(msg);
			req->r_reply =  ceph_msg_get(msg);
			req->r_got_result = true;
			set_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags);
		}
		}
	} else {
	} else {
		dout("reply arrived after request %lld was aborted\n", tid);
		dout("reply arrived after request %lld was aborted\n", tid);
@@ -2587,7 +2590,7 @@ static void handle_forward(struct ceph_mds_client *mdsc,
		goto out;  /* dup reply? */
		goto out;  /* dup reply? */
	}
	}


	if (req->r_aborted) {
	if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
		dout("forward tid %llu aborted, unregistering\n", tid);
		dout("forward tid %llu aborted, unregistering\n", tid);
		__unregister_request(mdsc, req);
		__unregister_request(mdsc, req);
	} else if (fwd_seq <= req->r_num_fwd) {
	} else if (fwd_seq <= req->r_num_fwd) {
@@ -2597,7 +2600,7 @@ static void handle_forward(struct ceph_mds_client *mdsc,
		/* resend. forward race not possible; mds would drop */
		/* resend. forward race not possible; mds would drop */
		dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds);
		dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds);
		BUG_ON(req->r_err);
		BUG_ON(req->r_err);
		BUG_ON(req->r_got_result);
		BUG_ON(test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags));
		req->r_attempts = 0;
		req->r_attempts = 0;
		req->r_num_fwd = fwd_seq;
		req->r_num_fwd = fwd_seq;
		req->r_resend_mds = next_mds;
		req->r_resend_mds = next_mds;
@@ -2762,7 +2765,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
	while (p) {
	while (p) {
		req = rb_entry(p, struct ceph_mds_request, r_node);
		req = rb_entry(p, struct ceph_mds_request, r_node);
		p = rb_next(p);
		p = rb_next(p);
		if (req->r_got_unsafe)
		if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags))
			continue;
			continue;
		if (req->r_attempts == 0)
		if (req->r_attempts == 0)
			continue; /* only old requests */
			continue; /* only old requests */
+8 −4
Original line number Original line Diff line number Diff line
@@ -205,6 +205,14 @@ struct ceph_mds_request {
	struct inode *r_locked_dir; /* dir (if any) i_mutex locked by vfs */
	struct inode *r_locked_dir; /* dir (if any) i_mutex locked by vfs */
	struct inode *r_target_inode;       /* resulting inode */
	struct inode *r_target_inode;       /* resulting inode */


#define CEPH_MDS_R_DIRECT_IS_HASH	(1) /* r_direct_hash is valid */
#define CEPH_MDS_R_ABORTED		(2) /* call was aborted */
#define CEPH_MDS_R_GOT_UNSAFE		(3) /* got an unsafe reply */
#define CEPH_MDS_R_GOT_SAFE		(4) /* got a safe reply */
#define CEPH_MDS_R_GOT_RESULT		(5) /* got a result */
#define CEPH_MDS_R_DID_PREPOPULATE	(6) /* prepopulated readdir */
	unsigned long	r_req_flags;

	struct mutex r_fill_mutex;
	struct mutex r_fill_mutex;


	union ceph_mds_request_args r_args;
	union ceph_mds_request_args r_args;
@@ -216,7 +224,6 @@ struct ceph_mds_request {
	/* for choosing which mds to send this request to */
	/* for choosing which mds to send this request to */
	int r_direct_mode;
	int r_direct_mode;
	u32 r_direct_hash;      /* choose dir frag based on this dentry hash */
	u32 r_direct_hash;      /* choose dir frag based on this dentry hash */
	bool r_direct_is_hash;  /* true if r_direct_hash is valid */


	/* data payload is used for xattr ops */
	/* data payload is used for xattr ops */
	struct ceph_pagelist *r_pagelist;
	struct ceph_pagelist *r_pagelist;
@@ -234,7 +241,6 @@ struct ceph_mds_request {
	struct ceph_mds_reply_info_parsed r_reply_info;
	struct ceph_mds_reply_info_parsed r_reply_info;
	struct page *r_locked_page;
	struct page *r_locked_page;
	int r_err;
	int r_err;
	bool r_aborted;


	unsigned long r_timeout;  /* optional.  jiffies, 0 is "wait forever" */
	unsigned long r_timeout;  /* optional.  jiffies, 0 is "wait forever" */
	unsigned long r_started;  /* start time to measure timeout against */
	unsigned long r_started;  /* start time to measure timeout against */
@@ -262,9 +268,7 @@ struct ceph_mds_request {
	ceph_mds_request_callback_t r_callback;
	ceph_mds_request_callback_t r_callback;
	ceph_mds_request_wait_callback_t r_wait_for_completion;
	ceph_mds_request_wait_callback_t r_wait_for_completion;
	struct list_head  r_unsafe_item;  /* per-session unsafe list item */
	struct list_head  r_unsafe_item;  /* per-session unsafe list item */
	bool		  r_got_unsafe, r_got_safe, r_got_result;


	bool              r_did_prepopulate;
	long long	  r_dir_release_cnt;
	long long	  r_dir_release_cnt;
	long long	  r_dir_ordered_cnt;
	long long	  r_dir_ordered_cnt;
	int		  r_readdir_cache_idx;
	int		  r_readdir_cache_idx;