summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2018-04-26 23:11:31 -0400
committerIlya Dryomov <idryomov@gmail.com>2018-06-04 14:45:56 -0400
commit4985d6f9e50fa48e35a9dbe1726434f987305cae (patch)
tree4b5c7a54f2b9e71564c5b37cf7b23e7fe93c5307 /fs/ceph/caps.c
parenta1c6b8358171c16db0f858a7fbb28aa574b07c09 (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.c39
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);