diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
| -rw-r--r-- | fs/ceph/mds_client.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 1766947fc07a..416c08d315db 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
| @@ -1514,6 +1514,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, | |||
| 1514 | ceph_encode_filepath(&p, end, ino1, path1); | 1514 | ceph_encode_filepath(&p, end, ino1, path1); |
| 1515 | ceph_encode_filepath(&p, end, ino2, path2); | 1515 | ceph_encode_filepath(&p, end, ino2, path2); |
| 1516 | 1516 | ||
| 1517 | /* make note of release offset, in case we need to replay */ | ||
| 1518 | req->r_request_release_offset = p - msg->front.iov_base; | ||
| 1519 | |||
| 1517 | /* cap releases */ | 1520 | /* cap releases */ |
| 1518 | releases = 0; | 1521 | releases = 0; |
| 1519 | if (req->r_inode_drop) | 1522 | if (req->r_inode_drop) |
| @@ -1580,6 +1583,32 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc, | |||
| 1580 | dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req, | 1583 | 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); | 1584 | req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts); |
| 1582 | 1585 | ||
| 1586 | if (req->r_got_unsafe) { | ||
| 1587 | /* | ||
| 1588 | * Replay. Do not regenerate message (and rebuild | ||
| 1589 | * paths, etc.); just use the original message. | ||
| 1590 | * Rebuilding paths will break for renames because | ||
| 1591 | * d_move mangles the src name. | ||
| 1592 | */ | ||
| 1593 | msg = req->r_request; | ||
| 1594 | rhead = msg->front.iov_base; | ||
| 1595 | |||
| 1596 | flags = le32_to_cpu(rhead->flags); | ||
| 1597 | flags |= CEPH_MDS_FLAG_REPLAY; | ||
| 1598 | rhead->flags = cpu_to_le32(flags); | ||
| 1599 | |||
| 1600 | if (req->r_target_inode) | ||
| 1601 | rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode)); | ||
| 1602 | |||
| 1603 | rhead->num_retry = req->r_attempts - 1; | ||
| 1604 | |||
| 1605 | /* remove cap/dentry releases from message */ | ||
| 1606 | rhead->num_releases = 0; | ||
| 1607 | msg->hdr.front_len = cpu_to_le32(req->r_request_release_offset); | ||
| 1608 | msg->front.iov_len = req->r_request_release_offset; | ||
| 1609 | return 0; | ||
| 1610 | } | ||
| 1611 | |||
| 1583 | if (req->r_request) { | 1612 | if (req->r_request) { |
| 1584 | ceph_msg_put(req->r_request); | 1613 | ceph_msg_put(req->r_request); |
| 1585 | req->r_request = NULL; | 1614 | req->r_request = NULL; |
| @@ -1601,13 +1630,9 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc, | |||
| 1601 | rhead->flags = cpu_to_le32(flags); | 1630 | rhead->flags = cpu_to_le32(flags); |
| 1602 | rhead->num_fwd = req->r_num_fwd; | 1631 | rhead->num_fwd = req->r_num_fwd; |
| 1603 | rhead->num_retry = req->r_attempts - 1; | 1632 | rhead->num_retry = req->r_attempts - 1; |
| 1633 | rhead->ino = 0; | ||
| 1604 | 1634 | ||
| 1605 | dout(" r_locked_dir = %p\n", req->r_locked_dir); | 1635 | 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; | 1636 | return 0; |
| 1612 | } | 1637 | } |
| 1613 | 1638 | ||
| @@ -2783,6 +2808,12 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) | |||
| 2783 | drop_leases(mdsc); | 2808 | drop_leases(mdsc); |
| 2784 | ceph_flush_dirty_caps(mdsc); | 2809 | ceph_flush_dirty_caps(mdsc); |
| 2785 | wait_requests(mdsc); | 2810 | wait_requests(mdsc); |
| 2811 | |||
| 2812 | /* | ||
| 2813 | * wait for reply handlers to drop their request refs and | ||
| 2814 | * their inode/dcache refs | ||
| 2815 | */ | ||
| 2816 | ceph_msgr_flush(); | ||
| 2786 | } | 2817 | } |
| 2787 | 2818 | ||
| 2788 | /* | 2819 | /* |
