diff options
author | Yan, Zheng <zyan@redhat.com> | 2018-04-26 23:11:31 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2018-06-04 14:45:56 -0400 |
commit | 4985d6f9e50fa48e35a9dbe1726434f987305cae (patch) | |
tree | 4b5c7a54f2b9e71564c5b37cf7b23e7fe93c5307 /fs/ceph/caps.c | |
parent | a1c6b8358171c16db0f858a7fbb28aa574b07c09 (diff) |
ceph: handle the new nfiles/nsubdirs fields in cap message
Without these new fields, stale st_size is returned in following
case.
1. MDS modifies a directory
2. MDS issues CEPH_CAP_ANY_SHARED to client
3. The client satifies stat(2) by its cached metadata. set st_size
to "i_files + i_subdirs".
Link: http://tracker.ceph.com/issues/23855
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index de7b7a34195e..477b822e6333 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -3030,6 +3030,10 @@ struct cap_extra_info { | |||
3030 | u64 inline_version; | 3030 | u64 inline_version; |
3031 | void *inline_data; | 3031 | void *inline_data; |
3032 | u32 inline_len; | 3032 | u32 inline_len; |
3033 | /* dirstat */ | ||
3034 | bool dirstat_valid; | ||
3035 | u64 nfiles; | ||
3036 | u64 nsubdirs; | ||
3033 | /* currently issued */ | 3037 | /* currently issued */ |
3034 | int issued; | 3038 | int issued; |
3035 | }; | 3039 | }; |
@@ -3154,6 +3158,11 @@ static void handle_cap_grant(struct inode *inode, | |||
3154 | &ctime, &mtime, &atime); | 3158 | &ctime, &mtime, &atime); |
3155 | } | 3159 | } |
3156 | 3160 | ||
3161 | if ((newcaps & CEPH_CAP_FILE_SHARED) && extra_info->dirstat_valid) { | ||
3162 | ci->i_files = extra_info->nfiles; | ||
3163 | ci->i_subdirs = extra_info->nsubdirs; | ||
3164 | } | ||
3165 | |||
3157 | if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) { | 3166 | if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) { |
3158 | /* file layout may have changed */ | 3167 | /* file layout may have changed */ |
3159 | s64 old_pool = ci->i_layout.pool_id; | 3168 | s64 old_pool = ci->i_layout.pool_id; |
@@ -3741,6 +3750,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3741 | struct ceph_mds_cap_peer *peer = NULL; | 3750 | struct ceph_mds_cap_peer *peer = NULL; |
3742 | struct ceph_snap_realm *realm = NULL; | 3751 | struct ceph_snap_realm *realm = NULL; |
3743 | int op; | 3752 | int op; |
3753 | int msg_version = le16_to_cpu(msg->hdr.version); | ||
3744 | u32 seq, mseq; | 3754 | u32 seq, mseq; |
3745 | struct ceph_vino vino; | 3755 | struct ceph_vino vino; |
3746 | void *snaptrace; | 3756 | void *snaptrace; |
@@ -3765,7 +3775,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3765 | snaptrace_len = le32_to_cpu(h->snap_trace_len); | 3775 | snaptrace_len = le32_to_cpu(h->snap_trace_len); |
3766 | p = snaptrace + snaptrace_len; | 3776 | p = snaptrace + snaptrace_len; |
3767 | 3777 | ||
3768 | if (le16_to_cpu(msg->hdr.version) >= 2) { | 3778 | if (msg_version >= 2) { |
3769 | u32 flock_len; | 3779 | u32 flock_len; |
3770 | ceph_decode_32_safe(&p, end, flock_len, bad); | 3780 | ceph_decode_32_safe(&p, end, flock_len, bad); |
3771 | if (p + flock_len > end) | 3781 | if (p + flock_len > end) |
@@ -3773,7 +3783,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3773 | p += flock_len; | 3783 | p += flock_len; |
3774 | } | 3784 | } |
3775 | 3785 | ||
3776 | if (le16_to_cpu(msg->hdr.version) >= 3) { | 3786 | if (msg_version >= 3) { |
3777 | if (op == CEPH_CAP_OP_IMPORT) { | 3787 | if (op == CEPH_CAP_OP_IMPORT) { |
3778 | if (p + sizeof(*peer) > end) | 3788 | if (p + sizeof(*peer) > end) |
3779 | goto bad; | 3789 | goto bad; |
@@ -3785,7 +3795,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3785 | } | 3795 | } |
3786 | } | 3796 | } |
3787 | 3797 | ||
3788 | if (le16_to_cpu(msg->hdr.version) >= 4) { | 3798 | if (msg_version >= 4) { |
3789 | ceph_decode_64_safe(&p, end, extra_info.inline_version, bad); | 3799 | ceph_decode_64_safe(&p, end, extra_info.inline_version, bad); |
3790 | ceph_decode_32_safe(&p, end, extra_info.inline_len, bad); | 3800 | ceph_decode_32_safe(&p, end, extra_info.inline_len, bad); |
3791 | if (p + extra_info.inline_len > end) | 3801 | if (p + extra_info.inline_len > end) |
@@ -3794,7 +3804,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3794 | p += extra_info.inline_len; | 3804 | p += extra_info.inline_len; |
3795 | } | 3805 | } |
3796 | 3806 | ||
3797 | if (le16_to_cpu(msg->hdr.version) >= 5) { | 3807 | if (msg_version >= 5) { |
3798 | struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc; | 3808 | struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc; |
3799 | u32 epoch_barrier; | 3809 | u32 epoch_barrier; |
3800 | 3810 | ||
@@ -3802,7 +3812,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3802 | ceph_osdc_update_epoch_barrier(osdc, epoch_barrier); | 3812 | ceph_osdc_update_epoch_barrier(osdc, epoch_barrier); |
3803 | } | 3813 | } |
3804 | 3814 | ||
3805 | if (le16_to_cpu(msg->hdr.version) >= 8) { | 3815 | if (msg_version >= 8) { |
3806 | u64 flush_tid; | 3816 | u64 flush_tid; |
3807 | u32 caller_uid, caller_gid; | 3817 | u32 caller_uid, caller_gid; |
3808 | u32 pool_ns_len; | 3818 | u32 pool_ns_len; |
@@ -3822,6 +3832,25 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
3822 | } | 3832 | } |
3823 | } | 3833 | } |
3824 | 3834 | ||
3835 | if (msg_version >= 11) { | ||
3836 | struct ceph_timespec *btime; | ||
3837 | u64 change_attr; | ||
3838 | u32 flags; | ||
3839 | |||
3840 | /* version >= 9 */ | ||
3841 | if (p + sizeof(*btime) > end) | ||
3842 | goto bad; | ||
3843 | btime = p; | ||
3844 | p += sizeof(*btime); | ||
3845 | ceph_decode_64_safe(&p, end, change_attr, bad); | ||
3846 | /* version >= 10 */ | ||
3847 | ceph_decode_32_safe(&p, end, flags, bad); | ||
3848 | /* version >= 11 */ | ||
3849 | extra_info.dirstat_valid = true; | ||
3850 | ceph_decode_64_safe(&p, end, extra_info.nfiles, bad); | ||
3851 | ceph_decode_64_safe(&p, end, extra_info.nsubdirs, bad); | ||
3852 | } | ||
3853 | |||
3825 | /* lookup ino */ | 3854 | /* lookup ino */ |
3826 | inode = ceph_find_inode(mdsc->fsc->sb, vino); | 3855 | inode = ceph_find_inode(mdsc->fsc->sb, vino); |
3827 | ci = ceph_inode(inode); | 3856 | ci = ceph_inode(inode); |