diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 132 |
1 files changed, 84 insertions, 48 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index d90861f45210..f4f050a69a48 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -63,7 +63,7 @@ static const struct ceph_connection_operations mds_con_ops; | |||
63 | */ | 63 | */ |
64 | static int parse_reply_info_in(void **p, void *end, | 64 | static int parse_reply_info_in(void **p, void *end, |
65 | struct ceph_mds_reply_info_in *info, | 65 | struct ceph_mds_reply_info_in *info, |
66 | int features) | 66 | u64 features) |
67 | { | 67 | { |
68 | int err = -EIO; | 68 | int err = -EIO; |
69 | 69 | ||
@@ -98,7 +98,7 @@ bad: | |||
98 | */ | 98 | */ |
99 | static int parse_reply_info_trace(void **p, void *end, | 99 | static int parse_reply_info_trace(void **p, void *end, |
100 | struct ceph_mds_reply_info_parsed *info, | 100 | struct ceph_mds_reply_info_parsed *info, |
101 | int features) | 101 | u64 features) |
102 | { | 102 | { |
103 | int err; | 103 | int err; |
104 | 104 | ||
@@ -145,7 +145,7 @@ out_bad: | |||
145 | */ | 145 | */ |
146 | static int parse_reply_info_dir(void **p, void *end, | 146 | static int parse_reply_info_dir(void **p, void *end, |
147 | struct ceph_mds_reply_info_parsed *info, | 147 | struct ceph_mds_reply_info_parsed *info, |
148 | int features) | 148 | u64 features) |
149 | { | 149 | { |
150 | u32 num, i = 0; | 150 | u32 num, i = 0; |
151 | int err; | 151 | int err; |
@@ -217,7 +217,7 @@ out_bad: | |||
217 | */ | 217 | */ |
218 | static int parse_reply_info_filelock(void **p, void *end, | 218 | static int parse_reply_info_filelock(void **p, void *end, |
219 | struct ceph_mds_reply_info_parsed *info, | 219 | struct ceph_mds_reply_info_parsed *info, |
220 | int features) | 220 | u64 features) |
221 | { | 221 | { |
222 | if (*p + sizeof(*info->filelock_reply) > end) | 222 | if (*p + sizeof(*info->filelock_reply) > end) |
223 | goto bad; | 223 | goto bad; |
@@ -238,7 +238,7 @@ bad: | |||
238 | */ | 238 | */ |
239 | static int parse_reply_info_create(void **p, void *end, | 239 | static int parse_reply_info_create(void **p, void *end, |
240 | struct ceph_mds_reply_info_parsed *info, | 240 | struct ceph_mds_reply_info_parsed *info, |
241 | int features) | 241 | u64 features) |
242 | { | 242 | { |
243 | if (features & CEPH_FEATURE_REPLY_CREATE_INODE) { | 243 | if (features & CEPH_FEATURE_REPLY_CREATE_INODE) { |
244 | if (*p == end) { | 244 | if (*p == end) { |
@@ -262,7 +262,7 @@ bad: | |||
262 | */ | 262 | */ |
263 | static int parse_reply_info_extra(void **p, void *end, | 263 | static int parse_reply_info_extra(void **p, void *end, |
264 | struct ceph_mds_reply_info_parsed *info, | 264 | struct ceph_mds_reply_info_parsed *info, |
265 | int features) | 265 | u64 features) |
266 | { | 266 | { |
267 | if (info->head->op == CEPH_MDS_OP_GETFILELOCK) | 267 | if (info->head->op == CEPH_MDS_OP_GETFILELOCK) |
268 | return parse_reply_info_filelock(p, end, info, features); | 268 | return parse_reply_info_filelock(p, end, info, features); |
@@ -280,7 +280,7 @@ static int parse_reply_info_extra(void **p, void *end, | |||
280 | */ | 280 | */ |
281 | static int parse_reply_info(struct ceph_msg *msg, | 281 | static int parse_reply_info(struct ceph_msg *msg, |
282 | struct ceph_mds_reply_info_parsed *info, | 282 | struct ceph_mds_reply_info_parsed *info, |
283 | int features) | 283 | u64 features) |
284 | { | 284 | { |
285 | void *p, *end; | 285 | void *p, *end; |
286 | u32 len; | 286 | u32 len; |
@@ -713,14 +713,15 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
713 | struct dentry *dn = get_nonsnap_parent(parent); | 713 | struct dentry *dn = get_nonsnap_parent(parent); |
714 | inode = dn->d_inode; | 714 | inode = dn->d_inode; |
715 | dout("__choose_mds using nonsnap parent %p\n", inode); | 715 | dout("__choose_mds using nonsnap parent %p\n", inode); |
716 | } else if (req->r_dentry->d_inode) { | 716 | } else { |
717 | /* dentry target */ | 717 | /* dentry target */ |
718 | inode = req->r_dentry->d_inode; | 718 | inode = req->r_dentry->d_inode; |
719 | } else { | 719 | if (!inode || mode == USE_AUTH_MDS) { |
720 | /* dir + name */ | 720 | /* dir + name */ |
721 | inode = dir; | 721 | inode = dir; |
722 | hash = ceph_dentry_hash(dir, req->r_dentry); | 722 | hash = ceph_dentry_hash(dir, req->r_dentry); |
723 | is_hash = true; | 723 | is_hash = true; |
724 | } | ||
724 | } | 725 | } |
725 | } | 726 | } |
726 | 727 | ||
@@ -846,35 +847,56 @@ static int __open_session(struct ceph_mds_client *mdsc, | |||
846 | * | 847 | * |
847 | * called under mdsc->mutex | 848 | * called under mdsc->mutex |
848 | */ | 849 | */ |
850 | static struct ceph_mds_session * | ||
851 | __open_export_target_session(struct ceph_mds_client *mdsc, int target) | ||
852 | { | ||
853 | struct ceph_mds_session *session; | ||
854 | |||
855 | session = __ceph_lookup_mds_session(mdsc, target); | ||
856 | if (!session) { | ||
857 | session = register_session(mdsc, target); | ||
858 | if (IS_ERR(session)) | ||
859 | return session; | ||
860 | } | ||
861 | if (session->s_state == CEPH_MDS_SESSION_NEW || | ||
862 | session->s_state == CEPH_MDS_SESSION_CLOSING) | ||
863 | __open_session(mdsc, session); | ||
864 | |||
865 | return session; | ||
866 | } | ||
867 | |||
868 | struct ceph_mds_session * | ||
869 | ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target) | ||
870 | { | ||
871 | struct ceph_mds_session *session; | ||
872 | |||
873 | dout("open_export_target_session to mds%d\n", target); | ||
874 | |||
875 | mutex_lock(&mdsc->mutex); | ||
876 | session = __open_export_target_session(mdsc, target); | ||
877 | mutex_unlock(&mdsc->mutex); | ||
878 | |||
879 | return session; | ||
880 | } | ||
881 | |||
849 | static void __open_export_target_sessions(struct ceph_mds_client *mdsc, | 882 | static void __open_export_target_sessions(struct ceph_mds_client *mdsc, |
850 | struct ceph_mds_session *session) | 883 | struct ceph_mds_session *session) |
851 | { | 884 | { |
852 | struct ceph_mds_info *mi; | 885 | struct ceph_mds_info *mi; |
853 | struct ceph_mds_session *ts; | 886 | struct ceph_mds_session *ts; |
854 | int i, mds = session->s_mds; | 887 | int i, mds = session->s_mds; |
855 | int target; | ||
856 | 888 | ||
857 | if (mds >= mdsc->mdsmap->m_max_mds) | 889 | if (mds >= mdsc->mdsmap->m_max_mds) |
858 | return; | 890 | return; |
891 | |||
859 | mi = &mdsc->mdsmap->m_info[mds]; | 892 | mi = &mdsc->mdsmap->m_info[mds]; |
860 | dout("open_export_target_sessions for mds%d (%d targets)\n", | 893 | dout("open_export_target_sessions for mds%d (%d targets)\n", |
861 | session->s_mds, mi->num_export_targets); | 894 | session->s_mds, mi->num_export_targets); |
862 | 895 | ||
863 | for (i = 0; i < mi->num_export_targets; i++) { | 896 | for (i = 0; i < mi->num_export_targets; i++) { |
864 | target = mi->export_targets[i]; | 897 | ts = __open_export_target_session(mdsc, mi->export_targets[i]); |
865 | ts = __ceph_lookup_mds_session(mdsc, target); | 898 | if (!IS_ERR(ts)) |
866 | if (!ts) { | 899 | ceph_put_mds_session(ts); |
867 | ts = register_session(mdsc, target); | ||
868 | if (IS_ERR(ts)) | ||
869 | return; | ||
870 | } | ||
871 | if (session->s_state == CEPH_MDS_SESSION_NEW || | ||
872 | session->s_state == CEPH_MDS_SESSION_CLOSING) | ||
873 | __open_session(mdsc, session); | ||
874 | else | ||
875 | dout(" mds%d target mds%d %p is %s\n", session->s_mds, | ||
876 | i, ts, session_state_name(ts->s_state)); | ||
877 | ceph_put_mds_session(ts); | ||
878 | } | 900 | } |
879 | } | 901 | } |
880 | 902 | ||
@@ -1136,6 +1158,21 @@ static int send_renew_caps(struct ceph_mds_client *mdsc, | |||
1136 | return 0; | 1158 | return 0; |
1137 | } | 1159 | } |
1138 | 1160 | ||
1161 | static int send_flushmsg_ack(struct ceph_mds_client *mdsc, | ||
1162 | struct ceph_mds_session *session, u64 seq) | ||
1163 | { | ||
1164 | struct ceph_msg *msg; | ||
1165 | |||
1166 | dout("send_flushmsg_ack to mds%d (%s)s seq %lld\n", | ||
1167 | session->s_mds, session_state_name(session->s_state), seq); | ||
1168 | msg = create_session_msg(CEPH_SESSION_FLUSHMSG_ACK, seq); | ||
1169 | if (!msg) | ||
1170 | return -ENOMEM; | ||
1171 | ceph_con_send(&session->s_con, msg); | ||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1175 | |||
1139 | /* | 1176 | /* |
1140 | * Note new cap ttl, and any transition from stale -> not stale (fresh?). | 1177 | * Note new cap ttl, and any transition from stale -> not stale (fresh?). |
1141 | * | 1178 | * |
@@ -1214,7 +1251,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) | |||
1214 | { | 1251 | { |
1215 | struct ceph_mds_session *session = arg; | 1252 | struct ceph_mds_session *session = arg; |
1216 | struct ceph_inode_info *ci = ceph_inode(inode); | 1253 | struct ceph_inode_info *ci = ceph_inode(inode); |
1217 | int used, oissued, mine; | 1254 | int used, wanted, oissued, mine; |
1218 | 1255 | ||
1219 | if (session->s_trim_caps <= 0) | 1256 | if (session->s_trim_caps <= 0) |
1220 | return -1; | 1257 | return -1; |
@@ -1222,14 +1259,19 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) | |||
1222 | spin_lock(&ci->i_ceph_lock); | 1259 | spin_lock(&ci->i_ceph_lock); |
1223 | mine = cap->issued | cap->implemented; | 1260 | mine = cap->issued | cap->implemented; |
1224 | used = __ceph_caps_used(ci); | 1261 | used = __ceph_caps_used(ci); |
1262 | wanted = __ceph_caps_file_wanted(ci); | ||
1225 | oissued = __ceph_caps_issued_other(ci, cap); | 1263 | oissued = __ceph_caps_issued_other(ci, cap); |
1226 | 1264 | ||
1227 | dout("trim_caps_cb %p cap %p mine %s oissued %s used %s\n", | 1265 | dout("trim_caps_cb %p cap %p mine %s oissued %s used %s wanted %s\n", |
1228 | inode, cap, ceph_cap_string(mine), ceph_cap_string(oissued), | 1266 | inode, cap, ceph_cap_string(mine), ceph_cap_string(oissued), |
1229 | ceph_cap_string(used)); | 1267 | ceph_cap_string(used), ceph_cap_string(wanted)); |
1230 | if (ci->i_dirty_caps) | 1268 | if (cap == ci->i_auth_cap) { |
1231 | goto out; /* dirty caps */ | 1269 | if (ci->i_dirty_caps | ci->i_flushing_caps) |
1232 | if ((used & ~oissued) & mine) | 1270 | goto out; |
1271 | if ((used | wanted) & CEPH_CAP_ANY_WR) | ||
1272 | goto out; | ||
1273 | } | ||
1274 | if ((used | wanted) & ~oissued & mine) | ||
1233 | goto out; /* we need these caps */ | 1275 | goto out; /* we need these caps */ |
1234 | 1276 | ||
1235 | session->s_trim_caps--; | 1277 | session->s_trim_caps--; |
@@ -2156,26 +2198,16 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2156 | */ | 2198 | */ |
2157 | if (result == -ESTALE) { | 2199 | if (result == -ESTALE) { |
2158 | dout("got ESTALE on request %llu", req->r_tid); | 2200 | dout("got ESTALE on request %llu", req->r_tid); |
2159 | if (!req->r_inode) { | 2201 | if (req->r_direct_mode != USE_AUTH_MDS) { |
2160 | /* do nothing; not an authority problem */ | ||
2161 | } else if (req->r_direct_mode != USE_AUTH_MDS) { | ||
2162 | dout("not using auth, setting for that now"); | 2202 | dout("not using auth, setting for that now"); |
2163 | req->r_direct_mode = USE_AUTH_MDS; | 2203 | req->r_direct_mode = USE_AUTH_MDS; |
2164 | __do_request(mdsc, req); | 2204 | __do_request(mdsc, req); |
2165 | mutex_unlock(&mdsc->mutex); | 2205 | mutex_unlock(&mdsc->mutex); |
2166 | goto out; | 2206 | goto out; |
2167 | } else { | 2207 | } else { |
2168 | struct ceph_inode_info *ci = ceph_inode(req->r_inode); | 2208 | int mds = __choose_mds(mdsc, req); |
2169 | struct ceph_cap *cap = NULL; | 2209 | if (mds >= 0 && mds != req->r_session->s_mds) { |
2170 | 2210 | dout("but auth changed, so resending"); | |
2171 | if (req->r_session) | ||
2172 | cap = ceph_get_cap_for_mds(ci, | ||
2173 | req->r_session->s_mds); | ||
2174 | |||
2175 | dout("already using auth"); | ||
2176 | if ((!cap || cap != ci->i_auth_cap) || | ||
2177 | (cap->mseq != req->r_sent_on_mseq)) { | ||
2178 | dout("but cap changed, so resending"); | ||
2179 | __do_request(mdsc, req); | 2211 | __do_request(mdsc, req); |
2180 | mutex_unlock(&mdsc->mutex); | 2212 | mutex_unlock(&mdsc->mutex); |
2181 | goto out; | 2213 | goto out; |
@@ -2400,6 +2432,10 @@ static void handle_session(struct ceph_mds_session *session, | |||
2400 | trim_caps(mdsc, session, le32_to_cpu(h->max_caps)); | 2432 | trim_caps(mdsc, session, le32_to_cpu(h->max_caps)); |
2401 | break; | 2433 | break; |
2402 | 2434 | ||
2435 | case CEPH_SESSION_FLUSHMSG: | ||
2436 | send_flushmsg_ack(mdsc, session, seq); | ||
2437 | break; | ||
2438 | |||
2403 | default: | 2439 | default: |
2404 | pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds); | 2440 | pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds); |
2405 | WARN_ON(1); | 2441 | WARN_ON(1); |