diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index a50fca1e03be..a1ee8fa3a8e7 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -60,7 +60,8 @@ static const struct ceph_connection_operations mds_con_ops; | |||
60 | * parse individual inode info | 60 | * parse individual inode info |
61 | */ | 61 | */ |
62 | static int parse_reply_info_in(void **p, void *end, | 62 | static int parse_reply_info_in(void **p, void *end, |
63 | struct ceph_mds_reply_info_in *info) | 63 | struct ceph_mds_reply_info_in *info, |
64 | int features) | ||
64 | { | 65 | { |
65 | int err = -EIO; | 66 | int err = -EIO; |
66 | 67 | ||
@@ -74,6 +75,12 @@ static int parse_reply_info_in(void **p, void *end, | |||
74 | info->symlink = *p; | 75 | info->symlink = *p; |
75 | *p += info->symlink_len; | 76 | *p += info->symlink_len; |
76 | 77 | ||
78 | if (features & CEPH_FEATURE_DIRLAYOUTHASH) | ||
79 | ceph_decode_copy_safe(p, end, &info->dir_layout, | ||
80 | sizeof(info->dir_layout), bad); | ||
81 | else | ||
82 | memset(&info->dir_layout, 0, sizeof(info->dir_layout)); | ||
83 | |||
77 | ceph_decode_32_safe(p, end, info->xattr_len, bad); | 84 | ceph_decode_32_safe(p, end, info->xattr_len, bad); |
78 | ceph_decode_need(p, end, info->xattr_len, bad); | 85 | ceph_decode_need(p, end, info->xattr_len, bad); |
79 | info->xattr_data = *p; | 86 | info->xattr_data = *p; |
@@ -88,12 +95,13 @@ bad: | |||
88 | * target inode. | 95 | * target inode. |
89 | */ | 96 | */ |
90 | static int parse_reply_info_trace(void **p, void *end, | 97 | static int parse_reply_info_trace(void **p, void *end, |
91 | struct ceph_mds_reply_info_parsed *info) | 98 | struct ceph_mds_reply_info_parsed *info, |
99 | int features) | ||
92 | { | 100 | { |
93 | int err; | 101 | int err; |
94 | 102 | ||
95 | if (info->head->is_dentry) { | 103 | if (info->head->is_dentry) { |
96 | err = parse_reply_info_in(p, end, &info->diri); | 104 | err = parse_reply_info_in(p, end, &info->diri, features); |
97 | if (err < 0) | 105 | if (err < 0) |
98 | goto out_bad; | 106 | goto out_bad; |
99 | 107 | ||
@@ -114,7 +122,7 @@ static int parse_reply_info_trace(void **p, void *end, | |||
114 | } | 122 | } |
115 | 123 | ||
116 | if (info->head->is_target) { | 124 | if (info->head->is_target) { |
117 | err = parse_reply_info_in(p, end, &info->targeti); | 125 | err = parse_reply_info_in(p, end, &info->targeti, features); |
118 | if (err < 0) | 126 | if (err < 0) |
119 | goto out_bad; | 127 | goto out_bad; |
120 | } | 128 | } |
@@ -134,7 +142,8 @@ out_bad: | |||
134 | * parse readdir results | 142 | * parse readdir results |
135 | */ | 143 | */ |
136 | static int parse_reply_info_dir(void **p, void *end, | 144 | static int parse_reply_info_dir(void **p, void *end, |
137 | struct ceph_mds_reply_info_parsed *info) | 145 | struct ceph_mds_reply_info_parsed *info, |
146 | int features) | ||
138 | { | 147 | { |
139 | u32 num, i = 0; | 148 | u32 num, i = 0; |
140 | int err; | 149 | int err; |
@@ -182,7 +191,7 @@ static int parse_reply_info_dir(void **p, void *end, | |||
182 | *p += sizeof(struct ceph_mds_reply_lease); | 191 | *p += sizeof(struct ceph_mds_reply_lease); |
183 | 192 | ||
184 | /* inode */ | 193 | /* inode */ |
185 | err = parse_reply_info_in(p, end, &info->dir_in[i]); | 194 | err = parse_reply_info_in(p, end, &info->dir_in[i], features); |
186 | if (err < 0) | 195 | if (err < 0) |
187 | goto out_bad; | 196 | goto out_bad; |
188 | i++; | 197 | i++; |
@@ -205,7 +214,8 @@ out_bad: | |||
205 | * parse fcntl F_GETLK results | 214 | * parse fcntl F_GETLK results |
206 | */ | 215 | */ |
207 | static int parse_reply_info_filelock(void **p, void *end, | 216 | static int parse_reply_info_filelock(void **p, void *end, |
208 | struct ceph_mds_reply_info_parsed *info) | 217 | struct ceph_mds_reply_info_parsed *info, |
218 | int features) | ||
209 | { | 219 | { |
210 | if (*p + sizeof(*info->filelock_reply) > end) | 220 | if (*p + sizeof(*info->filelock_reply) > end) |
211 | goto bad; | 221 | goto bad; |
@@ -225,19 +235,21 @@ bad: | |||
225 | * parse extra results | 235 | * parse extra results |
226 | */ | 236 | */ |
227 | static int parse_reply_info_extra(void **p, void *end, | 237 | static int parse_reply_info_extra(void **p, void *end, |
228 | struct ceph_mds_reply_info_parsed *info) | 238 | struct ceph_mds_reply_info_parsed *info, |
239 | int features) | ||
229 | { | 240 | { |
230 | if (info->head->op == CEPH_MDS_OP_GETFILELOCK) | 241 | if (info->head->op == CEPH_MDS_OP_GETFILELOCK) |
231 | return parse_reply_info_filelock(p, end, info); | 242 | return parse_reply_info_filelock(p, end, info, features); |
232 | else | 243 | else |
233 | return parse_reply_info_dir(p, end, info); | 244 | return parse_reply_info_dir(p, end, info, features); |
234 | } | 245 | } |
235 | 246 | ||
236 | /* | 247 | /* |
237 | * parse entire mds reply | 248 | * parse entire mds reply |
238 | */ | 249 | */ |
239 | static int parse_reply_info(struct ceph_msg *msg, | 250 | static int parse_reply_info(struct ceph_msg *msg, |
240 | struct ceph_mds_reply_info_parsed *info) | 251 | struct ceph_mds_reply_info_parsed *info, |
252 | int features) | ||
241 | { | 253 | { |
242 | void *p, *end; | 254 | void *p, *end; |
243 | u32 len; | 255 | u32 len; |
@@ -250,7 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg, | |||
250 | /* trace */ | 262 | /* trace */ |
251 | ceph_decode_32_safe(&p, end, len, bad); | 263 | ceph_decode_32_safe(&p, end, len, bad); |
252 | if (len > 0) { | 264 | if (len > 0) { |
253 | err = parse_reply_info_trace(&p, p+len, info); | 265 | err = parse_reply_info_trace(&p, p+len, info, features); |
254 | if (err < 0) | 266 | if (err < 0) |
255 | goto out_bad; | 267 | goto out_bad; |
256 | } | 268 | } |
@@ -258,7 +270,7 @@ static int parse_reply_info(struct ceph_msg *msg, | |||
258 | /* extra */ | 270 | /* extra */ |
259 | ceph_decode_32_safe(&p, end, len, bad); | 271 | ceph_decode_32_safe(&p, end, len, bad); |
260 | if (len > 0) { | 272 | if (len > 0) { |
261 | err = parse_reply_info_extra(&p, p+len, info); | 273 | err = parse_reply_info_extra(&p, p+len, info, features); |
262 | if (err < 0) | 274 | if (err < 0) |
263 | goto out_bad; | 275 | goto out_bad; |
264 | } | 276 | } |
@@ -654,7 +666,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
654 | } else { | 666 | } else { |
655 | /* dir + name */ | 667 | /* dir + name */ |
656 | inode = dir; | 668 | inode = dir; |
657 | hash = req->r_dentry->d_name.hash; | 669 | hash = ceph_dentry_hash(req->r_dentry); |
658 | is_hash = true; | 670 | is_hash = true; |
659 | } | 671 | } |
660 | } | 672 | } |
@@ -681,9 +693,11 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
681 | dout("choose_mds %p %llx.%llx " | 693 | dout("choose_mds %p %llx.%llx " |
682 | "frag %u mds%d (%d/%d)\n", | 694 | "frag %u mds%d (%d/%d)\n", |
683 | inode, ceph_vinop(inode), | 695 | inode, ceph_vinop(inode), |
684 | frag.frag, frag.mds, | 696 | frag.frag, mds, |
685 | (int)r, frag.ndist); | 697 | (int)r, frag.ndist); |
686 | return mds; | 698 | if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >= |
699 | CEPH_MDS_STATE_ACTIVE) | ||
700 | return mds; | ||
687 | } | 701 | } |
688 | 702 | ||
689 | /* since this file/dir wasn't known to be | 703 | /* since this file/dir wasn't known to be |
@@ -696,7 +710,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
696 | dout("choose_mds %p %llx.%llx " | 710 | dout("choose_mds %p %llx.%llx " |
697 | "frag %u mds%d (auth)\n", | 711 | "frag %u mds%d (auth)\n", |
698 | inode, ceph_vinop(inode), frag.frag, mds); | 712 | inode, ceph_vinop(inode), frag.frag, mds); |
699 | return mds; | 713 | if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >= |
714 | CEPH_MDS_STATE_ACTIVE) | ||
715 | return mds; | ||
700 | } | 716 | } |
701 | } | 717 | } |
702 | } | 718 | } |
@@ -1693,7 +1709,6 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc, | |||
1693 | struct ceph_msg *msg; | 1709 | struct ceph_msg *msg; |
1694 | int flags = 0; | 1710 | int flags = 0; |
1695 | 1711 | ||
1696 | req->r_mds = mds; | ||
1697 | req->r_attempts++; | 1712 | req->r_attempts++; |
1698 | if (req->r_inode) { | 1713 | if (req->r_inode) { |
1699 | struct ceph_cap *cap = | 1714 | struct ceph_cap *cap = |
@@ -1780,6 +1795,8 @@ static int __do_request(struct ceph_mds_client *mdsc, | |||
1780 | goto finish; | 1795 | goto finish; |
1781 | } | 1796 | } |
1782 | 1797 | ||
1798 | put_request_session(req); | ||
1799 | |||
1783 | mds = __choose_mds(mdsc, req); | 1800 | mds = __choose_mds(mdsc, req); |
1784 | if (mds < 0 || | 1801 | if (mds < 0 || |
1785 | ceph_mdsmap_get_state(mdsc->mdsmap, mds) < CEPH_MDS_STATE_ACTIVE) { | 1802 | ceph_mdsmap_get_state(mdsc->mdsmap, mds) < CEPH_MDS_STATE_ACTIVE) { |
@@ -1797,6 +1814,8 @@ static int __do_request(struct ceph_mds_client *mdsc, | |||
1797 | goto finish; | 1814 | goto finish; |
1798 | } | 1815 | } |
1799 | } | 1816 | } |
1817 | req->r_session = get_session(session); | ||
1818 | |||
1800 | dout("do_request mds%d session %p state %s\n", mds, session, | 1819 | dout("do_request mds%d session %p state %s\n", mds, session, |
1801 | session_state_name(session->s_state)); | 1820 | session_state_name(session->s_state)); |
1802 | if (session->s_state != CEPH_MDS_SESSION_OPEN && | 1821 | if (session->s_state != CEPH_MDS_SESSION_OPEN && |
@@ -1809,7 +1828,6 @@ static int __do_request(struct ceph_mds_client *mdsc, | |||
1809 | } | 1828 | } |
1810 | 1829 | ||
1811 | /* send request */ | 1830 | /* send request */ |
1812 | req->r_session = get_session(session); | ||
1813 | req->r_resend_mds = -1; /* forget any previous mds hint */ | 1831 | req->r_resend_mds = -1; /* forget any previous mds hint */ |
1814 | 1832 | ||
1815 | if (req->r_request_started == 0) /* note request start time */ | 1833 | if (req->r_request_started == 0) /* note request start time */ |
@@ -1863,7 +1881,6 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds) | |||
1863 | if (req->r_session && | 1881 | if (req->r_session && |
1864 | req->r_session->s_mds == mds) { | 1882 | req->r_session->s_mds == mds) { |
1865 | dout(" kicking tid %llu\n", req->r_tid); | 1883 | dout(" kicking tid %llu\n", req->r_tid); |
1866 | put_request_session(req); | ||
1867 | __do_request(mdsc, req); | 1884 | __do_request(mdsc, req); |
1868 | } | 1885 | } |
1869 | } | 1886 | } |
@@ -2056,8 +2073,11 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2056 | goto out; | 2073 | goto out; |
2057 | } else { | 2074 | } else { |
2058 | struct ceph_inode_info *ci = ceph_inode(req->r_inode); | 2075 | struct ceph_inode_info *ci = ceph_inode(req->r_inode); |
2059 | struct ceph_cap *cap = | 2076 | struct ceph_cap *cap = NULL; |
2060 | ceph_get_cap_for_mds(ci, req->r_mds);; | 2077 | |
2078 | if (req->r_session) | ||
2079 | cap = ceph_get_cap_for_mds(ci, | ||
2080 | req->r_session->s_mds); | ||
2061 | 2081 | ||
2062 | dout("already using auth"); | 2082 | dout("already using auth"); |
2063 | if ((!cap || cap != ci->i_auth_cap) || | 2083 | if ((!cap || cap != ci->i_auth_cap) || |
@@ -2101,7 +2121,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2101 | 2121 | ||
2102 | dout("handle_reply tid %lld result %d\n", tid, result); | 2122 | dout("handle_reply tid %lld result %d\n", tid, result); |
2103 | rinfo = &req->r_reply_info; | 2123 | rinfo = &req->r_reply_info; |
2104 | err = parse_reply_info(msg, rinfo); | 2124 | err = parse_reply_info(msg, rinfo, session->s_con.peer_features); |
2105 | mutex_unlock(&mdsc->mutex); | 2125 | mutex_unlock(&mdsc->mutex); |
2106 | 2126 | ||
2107 | mutex_lock(&session->s_mutex); | 2127 | mutex_lock(&session->s_mutex); |