aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-07-15 16:24:32 -0400
committerSage Weil <sage@newdream.net>2010-07-16 13:30:17 -0400
commit01a92f174f8a3b99dbb5e02c86e7ee1e576737af (patch)
treead478397d935b4b09340408cbacf8c6d35dee9d1
parentf91d3471ccf1ca9a795f46c94b1ded8dd219940c (diff)
ceph: reuse request message when replaying against recovering mds
Replayed rename operations (after an mds failure/recovery) were broken because the request paths were regenerated from the dentry names, which get mangled when d_move() is called. Instead, resend the previous request message when replaying completed operations. Just make sure the REPLAY flag is set and the target ino is filled in. This fixes problems with workloads doing renames when the MDS restarts, where the rename operation appears to succeed, but on mds restart then fails (leading to client confusion, app breakage, etc.). Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/mds_client.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 3ab79f6c4ce8..23332bc44515 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1580,6 +1580,27 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
1580 dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req, 1580 dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req,
1581 req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts); 1581 req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts);
1582 1582
1583 if (req->r_got_unsafe) {
1584 /*
1585 * Replay. Do not regenerate message (and rebuild
1586 * paths, etc.); just use the original message.
1587 * Rebuilding paths will break for renames because
1588 * d_move mangles the src name.
1589 */
1590 msg = req->r_request;
1591 rhead = msg->front.iov_base;
1592
1593 flags = le32_to_cpu(rhead->flags);
1594 flags |= CEPH_MDS_FLAG_REPLAY;
1595 rhead->flags = cpu_to_le32(flags);
1596
1597 if (req->r_target_inode)
1598 rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode));
1599
1600 rhead->num_retry = req->r_attempts - 1;
1601 return 0;
1602 }
1603
1583 if (req->r_request) { 1604 if (req->r_request) {
1584 ceph_msg_put(req->r_request); 1605 ceph_msg_put(req->r_request);
1585 req->r_request = NULL; 1606 req->r_request = NULL;
@@ -1601,13 +1622,9 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
1601 rhead->flags = cpu_to_le32(flags); 1622 rhead->flags = cpu_to_le32(flags);
1602 rhead->num_fwd = req->r_num_fwd; 1623 rhead->num_fwd = req->r_num_fwd;
1603 rhead->num_retry = req->r_attempts - 1; 1624 rhead->num_retry = req->r_attempts - 1;
1625 rhead->ino = 0;
1604 1626
1605 dout(" r_locked_dir = %p\n", req->r_locked_dir); 1627 dout(" r_locked_dir = %p\n", req->r_locked_dir);
1606
1607 if (req->r_target_inode && req->r_got_unsafe)
1608 rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode));
1609 else
1610 rhead->ino = 0;
1611 return 0; 1628 return 0;
1612} 1629}
1613 1630