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

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
...@@ -70,7 +70,7 @@ static int mdsc_show(struct seq_file *s, void *p) ...@@ -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");
......
...@@ -371,7 +371,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) ...@@ -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) ...@@ -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 */
......
...@@ -1199,8 +1199,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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);
......
...@@ -644,13 +644,15 @@ static void __unregister_request(struct ceph_mds_client *mdsc, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 */
......
...@@ -205,6 +205,14 @@ struct ceph_mds_request { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment