Skip to content

Commit 60267ba

Browse files
committed
ceph: reencode gid_list when reconnecting
On reconnect, cap and dentry releases are dropped and the fields that follow must be reencoded into the freed space. Currently these are timestamp and gid_list, but gid_list isn't reencoded. This results in failed to decode message of type 24 v4: End of buffer errors on the MDS. While at it, make a change to encode gid_list unconditionally, without regard to what head/which version was used as a result of checking whether CEPH_FEATURE_FS_BTIME is supported or not. URL: https://tracker.ceph.com/issues/48618 Fixes: 4f1ddb1 ("ceph: implement updated ceph_mds_request_head structure") Signed-off-by: Ilya Dryomov <[email protected]> Reviewed-by: Jeff Layton <[email protected]>
1 parent 5c8fe58 commit 60267ba

File tree

1 file changed

+22
-31
lines changed

1 file changed

+22
-31
lines changed

fs/ceph/mds_client.c

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,6 +2475,22 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
24752475
return r;
24762476
}
24772477

2478+
static void encode_timestamp_and_gids(void **p,
2479+
const struct ceph_mds_request *req)
2480+
{
2481+
struct ceph_timespec ts;
2482+
int i;
2483+
2484+
ceph_encode_timespec64(&ts, &req->r_stamp);
2485+
ceph_encode_copy(p, &ts, sizeof(ts));
2486+
2487+
/* gid_list */
2488+
ceph_encode_32(p, req->r_cred->group_info->ngroups);
2489+
for (i = 0; i < req->r_cred->group_info->ngroups; i++)
2490+
ceph_encode_64(p, from_kgid(&init_user_ns,
2491+
req->r_cred->group_info->gid[i]));
2492+
}
2493+
24782494
/*
24792495
* called under mdsc->mutex
24802496
*/
@@ -2491,7 +2507,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
24912507
u64 ino1 = 0, ino2 = 0;
24922508
int pathlen1 = 0, pathlen2 = 0;
24932509
bool freepath1 = false, freepath2 = false;
2494-
int len, i;
2510+
int len;
24952511
u16 releases;
24962512
void *p, *end;
24972513
int ret;
@@ -2517,17 +2533,10 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
25172533
goto out_free1;
25182534
}
25192535

2520-
if (legacy) {
2521-
/* Old style */
2522-
len = sizeof(*head);
2523-
} else {
2524-
/* New style: add gid_list and any later fields */
2525-
len = sizeof(struct ceph_mds_request_head) + sizeof(u32) +
2526-
(sizeof(u64) * req->r_cred->group_info->ngroups);
2527-
}
2528-
2536+
len = legacy ? sizeof(*head) : sizeof(struct ceph_mds_request_head);
25292537
len += pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) +
25302538
sizeof(struct ceph_timespec);
2539+
len += sizeof(u32) + (sizeof(u64) * req->r_cred->group_info->ngroups);
25312540

25322541
/* calculate (max) length for cap releases */
25332542
len += sizeof(struct ceph_mds_request_release) *
@@ -2548,7 +2557,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
25482557
msg->hdr.tid = cpu_to_le64(req->r_tid);
25492558

25502559
/*
2551-
* The old ceph_mds_request_header didn't contain a version field, and
2560+
* The old ceph_mds_request_head didn't contain a version field, and
25522561
* one was added when we moved the message version from 3->4.
25532562
*/
25542563
if (legacy) {
@@ -2609,20 +2618,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
26092618

26102619
head->num_releases = cpu_to_le16(releases);
26112620

2612-
/* time stamp */
2613-
{
2614-
struct ceph_timespec ts;
2615-
ceph_encode_timespec64(&ts, &req->r_stamp);
2616-
ceph_encode_copy(&p, &ts, sizeof(ts));
2617-
}
2618-
2619-
/* gid list */
2620-
if (!legacy) {
2621-
ceph_encode_32(&p, req->r_cred->group_info->ngroups);
2622-
for (i = 0; i < req->r_cred->group_info->ngroups; i++)
2623-
ceph_encode_64(&p, from_kgid(&init_user_ns,
2624-
req->r_cred->group_info->gid[i]));
2625-
}
2621+
encode_timestamp_and_gids(&p, req);
26262622

26272623
if (WARN_ON_ONCE(p > end)) {
26282624
ceph_msg_put(msg);
@@ -2730,13 +2726,8 @@ static int __prepare_send_request(struct ceph_mds_session *session,
27302726
/* remove cap/dentry releases from message */
27312727
rhead->num_releases = 0;
27322728

2733-
/* time stamp */
27342729
p = msg->front.iov_base + req->r_request_release_offset;
2735-
{
2736-
struct ceph_timespec ts;
2737-
ceph_encode_timespec64(&ts, &req->r_stamp);
2738-
ceph_encode_copy(&p, &ts, sizeof(ts));
2739-
}
2730+
encode_timestamp_and_gids(&p, req);
27402731

27412732
msg->front.iov_len = p - msg->front.iov_base;
27422733
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);

0 commit comments

Comments
 (0)