summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/addr.c1
-rw-r--r--fs/ceph/caps.c160
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/file.c1
-rw-r--r--fs/ceph/inode.c67
-rw-r--r--fs/ceph/super.c35
-rw-r--r--fs/ceph/xattr.c60
7 files changed, 202 insertions, 124 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index c9cb2f33a6d6..afcc59ed7090 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1936,7 +1936,6 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
1936 err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false); 1936 err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);
1937 1937
1938 wr_req->r_mtime = ci->vfs_inode.i_mtime; 1938 wr_req->r_mtime = ci->vfs_inode.i_mtime;
1939 wr_req->r_abort_on_full = true;
1940 err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false); 1939 err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
1941 1940
1942 if (!err) 1941 if (!err)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 23dbfae16156..0ae41854d676 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -69,6 +69,8 @@ static char *gcap_string(char *s, int c)
69 *s++ = 'w'; 69 *s++ = 'w';
70 if (c & CEPH_CAP_GBUFFER) 70 if (c & CEPH_CAP_GBUFFER)
71 *s++ = 'b'; 71 *s++ = 'b';
72 if (c & CEPH_CAP_GWREXTEND)
73 *s++ = 'a';
72 if (c & CEPH_CAP_GLAZYIO) 74 if (c & CEPH_CAP_GLAZYIO)
73 *s++ = 'l'; 75 *s++ = 'l';
74 return s; 76 return s;
@@ -3022,30 +3024,41 @@ static void invalidate_aliases(struct inode *inode)
3022 dput(prev); 3024 dput(prev);
3023} 3025}
3024 3026
3027struct cap_extra_info {
3028 struct ceph_string *pool_ns;
3029 /* inline data */
3030 u64 inline_version;
3031 void *inline_data;
3032 u32 inline_len;
3033 /* dirstat */
3034 bool dirstat_valid;
3035 u64 nfiles;
3036 u64 nsubdirs;
3037 /* currently issued */
3038 int issued;
3039};
3040
3025/* 3041/*
3026 * Handle a cap GRANT message from the MDS. (Note that a GRANT may 3042 * Handle a cap GRANT message from the MDS. (Note that a GRANT may
3027 * actually be a revocation if it specifies a smaller cap set.) 3043 * actually be a revocation if it specifies a smaller cap set.)
3028 * 3044 *
3029 * caller holds s_mutex and i_ceph_lock, we drop both. 3045 * caller holds s_mutex and i_ceph_lock, we drop both.
3030 */ 3046 */
3031static void handle_cap_grant(struct ceph_mds_client *mdsc, 3047static void handle_cap_grant(struct inode *inode,
3032 struct inode *inode, struct ceph_mds_caps *grant,
3033 struct ceph_string **pns, u64 inline_version,
3034 void *inline_data, u32 inline_len,
3035 struct ceph_buffer *xattr_buf,
3036 struct ceph_mds_session *session, 3048 struct ceph_mds_session *session,
3037 struct ceph_cap *cap, int issued) 3049 struct ceph_cap *cap,
3050 struct ceph_mds_caps *grant,
3051 struct ceph_buffer *xattr_buf,
3052 struct cap_extra_info *extra_info)
3038 __releases(ci->i_ceph_lock) 3053 __releases(ci->i_ceph_lock)
3039 __releases(mdsc->snap_rwsem) 3054 __releases(session->s_mdsc->snap_rwsem)
3040{ 3055{
3041 struct ceph_inode_info *ci = ceph_inode(inode); 3056 struct ceph_inode_info *ci = ceph_inode(inode);
3042 int mds = session->s_mds;
3043 int seq = le32_to_cpu(grant->seq); 3057 int seq = le32_to_cpu(grant->seq);
3044 int newcaps = le32_to_cpu(grant->caps); 3058 int newcaps = le32_to_cpu(grant->caps);
3045 int used, wanted, dirty; 3059 int used, wanted, dirty;
3046 u64 size = le64_to_cpu(grant->size); 3060 u64 size = le64_to_cpu(grant->size);
3047 u64 max_size = le64_to_cpu(grant->max_size); 3061 u64 max_size = le64_to_cpu(grant->max_size);
3048 struct timespec mtime, atime, ctime;
3049 int check_caps = 0; 3062 int check_caps = 0;
3050 bool wake = false; 3063 bool wake = false;
3051 bool writeback = false; 3064 bool writeback = false;
@@ -3055,7 +3068,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
3055 bool fill_inline = false; 3068 bool fill_inline = false;
3056 3069
3057 dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", 3070 dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
3058 inode, cap, mds, seq, ceph_cap_string(newcaps)); 3071 inode, cap, session->s_mds, seq, ceph_cap_string(newcaps));
3059 dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, 3072 dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
3060 inode->i_size); 3073 inode->i_size);
3061 3074
@@ -3101,7 +3114,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
3101 __check_cap_issue(ci, cap, newcaps); 3114 __check_cap_issue(ci, cap, newcaps);
3102 3115
3103 if ((newcaps & CEPH_CAP_AUTH_SHARED) && 3116 if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
3104 (issued & CEPH_CAP_AUTH_EXCL) == 0) { 3117 (extra_info->issued & CEPH_CAP_AUTH_EXCL) == 0) {
3105 inode->i_mode = le32_to_cpu(grant->mode); 3118 inode->i_mode = le32_to_cpu(grant->mode);
3106 inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid)); 3119 inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
3107 inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid)); 3120 inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
@@ -3110,15 +3123,16 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
3110 from_kgid(&init_user_ns, inode->i_gid)); 3123 from_kgid(&init_user_ns, inode->i_gid));
3111 } 3124 }
3112 3125
3113 if ((newcaps & CEPH_CAP_AUTH_SHARED) && 3126 if ((newcaps & CEPH_CAP_LINK_SHARED) &&
3114 (issued & CEPH_CAP_LINK_EXCL) == 0) { 3127 (extra_info->issued & CEPH_CAP_LINK_EXCL) == 0) {
3115 set_nlink(inode, le32_to_cpu(grant->nlink)); 3128 set_nlink(inode, le32_to_cpu(grant->nlink));
3116 if (inode->i_nlink == 0 && 3129 if (inode->i_nlink == 0 &&
3117 (newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL))) 3130 (newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL)))
3118 deleted_inode = true; 3131 deleted_inode = true;
3119 } 3132 }
3120 3133
3121 if ((issued & CEPH_CAP_XATTR_EXCL) == 0 && grant->xattr_len) { 3134 if ((extra_info->issued & CEPH_CAP_XATTR_EXCL) == 0 &&
3135 grant->xattr_len) {
3122 int len = le32_to_cpu(grant->xattr_len); 3136 int len = le32_to_cpu(grant->xattr_len);
3123 u64 version = le64_to_cpu(grant->xattr_version); 3137 u64 version = le64_to_cpu(grant->xattr_version);
3124 3138
@@ -3134,15 +3148,21 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
3134 } 3148 }
3135 3149
3136 if (newcaps & CEPH_CAP_ANY_RD) { 3150 if (newcaps & CEPH_CAP_ANY_RD) {
3151 struct timespec mtime, atime, ctime;
3137 /* ctime/mtime/atime? */ 3152 /* ctime/mtime/atime? */
3138 ceph_decode_timespec(&mtime, &grant->mtime); 3153 ceph_decode_timespec(&mtime, &grant->mtime);
3139 ceph_decode_timespec(&atime, &grant->atime); 3154 ceph_decode_timespec(&atime, &grant->atime);
3140 ceph_decode_timespec(&ctime, &grant->ctime); 3155 ceph_decode_timespec(&ctime, &grant->ctime);
3141 ceph_fill_file_time(inode, issued, 3156 ceph_fill_file_time(inode, extra_info->issued,
3142 le32_to_cpu(grant->time_warp_seq), 3157 le32_to_cpu(grant->time_warp_seq),
3143 &ctime, &mtime, &atime); 3158 &ctime, &mtime, &atime);
3144 } 3159 }
3145 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
3146 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)) {
3147 /* file layout may have changed */ 3167 /* file layout may have changed */
3148 s64 old_pool = ci->i_layout.pool_id; 3168 s64 old_pool = ci->i_layout.pool_id;
@@ -3151,15 +3171,16 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
3151 ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout); 3171 ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout);
3152 old_ns = rcu_dereference_protected(ci->i_layout.pool_ns, 3172 old_ns = rcu_dereference_protected(ci->i_layout.pool_ns,
3153 lockdep_is_held(&ci->i_ceph_lock)); 3173 lockdep_is_held(&ci->i_ceph_lock));
3154 rcu_assign_pointer(ci->i_layout.pool_ns, *pns); 3174 rcu_assign_pointer(ci->i_layout.pool_ns, extra_info->pool_ns);
3155 3175
3156 if (ci->i_layout.pool_id != old_pool || *pns != old_ns) 3176 if (ci->i_layout.pool_id != old_pool ||
3177 extra_info->pool_ns != old_ns)
3157 ci->i_ceph_flags &= ~CEPH_I_POOL_PERM; 3178 ci->i_ceph_flags &= ~CEPH_I_POOL_PERM;
3158 3179
3159 *pns = old_ns; 3180 extra_info->pool_ns = old_ns;
3160 3181
3161 /* size/truncate_seq? */ 3182 /* size/truncate_seq? */
3162 queue_trunc = ceph_fill_file_size(inode, issued, 3183 queue_trunc = ceph_fill_file_size(inode, extra_info->issued,
3163 le32_to_cpu(grant->truncate_seq), 3184 le32_to_cpu(grant->truncate_seq),
3164 le64_to_cpu(grant->truncate_size), 3185 le64_to_cpu(grant->truncate_size),
3165 size); 3186 size);
@@ -3238,24 +3259,26 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
3238 } 3259 }
3239 BUG_ON(cap->issued & ~cap->implemented); 3260 BUG_ON(cap->issued & ~cap->implemented);
3240 3261
3241 if (inline_version > 0 && inline_version >= ci->i_inline_version) { 3262 if (extra_info->inline_version > 0 &&
3242 ci->i_inline_version = inline_version; 3263 extra_info->inline_version >= ci->i_inline_version) {
3264 ci->i_inline_version = extra_info->inline_version;
3243 if (ci->i_inline_version != CEPH_INLINE_NONE && 3265 if (ci->i_inline_version != CEPH_INLINE_NONE &&
3244 (newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO))) 3266 (newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
3245 fill_inline = true; 3267 fill_inline = true;
3246 } 3268 }
3247 3269
3248 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { 3270 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
3249 if (newcaps & ~issued) 3271 if (newcaps & ~extra_info->issued)
3250 wake = true; 3272 wake = true;
3251 kick_flushing_inode_caps(mdsc, session, inode); 3273 kick_flushing_inode_caps(session->s_mdsc, session, inode);
3252 up_read(&mdsc->snap_rwsem); 3274 up_read(&session->s_mdsc->snap_rwsem);
3253 } else { 3275 } else {
3254 spin_unlock(&ci->i_ceph_lock); 3276 spin_unlock(&ci->i_ceph_lock);
3255 } 3277 }
3256 3278
3257 if (fill_inline) 3279 if (fill_inline)
3258 ceph_fill_inline_data(inode, NULL, inline_data, inline_len); 3280 ceph_fill_inline_data(inode, NULL, extra_info->inline_data,
3281 extra_info->inline_len);
3259 3282
3260 if (queue_trunc) 3283 if (queue_trunc)
3261 ceph_queue_vmtruncate(inode); 3284 ceph_queue_vmtruncate(inode);
@@ -3720,31 +3743,25 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3720 struct ceph_msg *msg) 3743 struct ceph_msg *msg)
3721{ 3744{
3722 struct ceph_mds_client *mdsc = session->s_mdsc; 3745 struct ceph_mds_client *mdsc = session->s_mdsc;
3723 struct super_block *sb = mdsc->fsc->sb;
3724 struct inode *inode; 3746 struct inode *inode;
3725 struct ceph_inode_info *ci; 3747 struct ceph_inode_info *ci;
3726 struct ceph_cap *cap; 3748 struct ceph_cap *cap;
3727 struct ceph_mds_caps *h; 3749 struct ceph_mds_caps *h;
3728 struct ceph_mds_cap_peer *peer = NULL; 3750 struct ceph_mds_cap_peer *peer = NULL;
3729 struct ceph_snap_realm *realm = NULL; 3751 struct ceph_snap_realm *realm = NULL;
3730 struct ceph_string *pool_ns = NULL; 3752 int op;
3731 int mds = session->s_mds; 3753 int msg_version = le16_to_cpu(msg->hdr.version);
3732 int op, issued;
3733 u32 seq, mseq; 3754 u32 seq, mseq;
3734 struct ceph_vino vino; 3755 struct ceph_vino vino;
3735 u64 tid;
3736 u64 inline_version = 0;
3737 void *inline_data = NULL;
3738 u32 inline_len = 0;
3739 void *snaptrace; 3756 void *snaptrace;
3740 size_t snaptrace_len; 3757 size_t snaptrace_len;
3741 void *p, *end; 3758 void *p, *end;
3759 struct cap_extra_info extra_info = {};
3742 3760
3743 dout("handle_caps from mds%d\n", mds); 3761 dout("handle_caps from mds%d\n", session->s_mds);
3744 3762
3745 /* decode */ 3763 /* decode */
3746 end = msg->front.iov_base + msg->front.iov_len; 3764 end = msg->front.iov_base + msg->front.iov_len;
3747 tid = le64_to_cpu(msg->hdr.tid);
3748 if (msg->front.iov_len < sizeof(*h)) 3765 if (msg->front.iov_len < sizeof(*h))
3749 goto bad; 3766 goto bad;
3750 h = msg->front.iov_base; 3767 h = msg->front.iov_base;
@@ -3758,7 +3775,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3758 snaptrace_len = le32_to_cpu(h->snap_trace_len); 3775 snaptrace_len = le32_to_cpu(h->snap_trace_len);
3759 p = snaptrace + snaptrace_len; 3776 p = snaptrace + snaptrace_len;
3760 3777
3761 if (le16_to_cpu(msg->hdr.version) >= 2) { 3778 if (msg_version >= 2) {
3762 u32 flock_len; 3779 u32 flock_len;
3763 ceph_decode_32_safe(&p, end, flock_len, bad); 3780 ceph_decode_32_safe(&p, end, flock_len, bad);
3764 if (p + flock_len > end) 3781 if (p + flock_len > end)
@@ -3766,7 +3783,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3766 p += flock_len; 3783 p += flock_len;
3767 } 3784 }
3768 3785
3769 if (le16_to_cpu(msg->hdr.version) >= 3) { 3786 if (msg_version >= 3) {
3770 if (op == CEPH_CAP_OP_IMPORT) { 3787 if (op == CEPH_CAP_OP_IMPORT) {
3771 if (p + sizeof(*peer) > end) 3788 if (p + sizeof(*peer) > end)
3772 goto bad; 3789 goto bad;
@@ -3778,16 +3795,16 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3778 } 3795 }
3779 } 3796 }
3780 3797
3781 if (le16_to_cpu(msg->hdr.version) >= 4) { 3798 if (msg_version >= 4) {
3782 ceph_decode_64_safe(&p, end, inline_version, bad); 3799 ceph_decode_64_safe(&p, end, extra_info.inline_version, bad);
3783 ceph_decode_32_safe(&p, end, inline_len, bad); 3800 ceph_decode_32_safe(&p, end, extra_info.inline_len, bad);
3784 if (p + inline_len > end) 3801 if (p + extra_info.inline_len > end)
3785 goto bad; 3802 goto bad;
3786 inline_data = p; 3803 extra_info.inline_data = p;
3787 p += inline_len; 3804 p += extra_info.inline_len;
3788 } 3805 }
3789 3806
3790 if (le16_to_cpu(msg->hdr.version) >= 5) { 3807 if (msg_version >= 5) {
3791 struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc; 3808 struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc;
3792 u32 epoch_barrier; 3809 u32 epoch_barrier;
3793 3810
@@ -3795,7 +3812,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3795 ceph_osdc_update_epoch_barrier(osdc, epoch_barrier); 3812 ceph_osdc_update_epoch_barrier(osdc, epoch_barrier);
3796 } 3813 }
3797 3814
3798 if (le16_to_cpu(msg->hdr.version) >= 8) { 3815 if (msg_version >= 8) {
3799 u64 flush_tid; 3816 u64 flush_tid;
3800 u32 caller_uid, caller_gid; 3817 u32 caller_uid, caller_gid;
3801 u32 pool_ns_len; 3818 u32 pool_ns_len;
@@ -3809,13 +3826,33 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3809 ceph_decode_32_safe(&p, end, pool_ns_len, bad); 3826 ceph_decode_32_safe(&p, end, pool_ns_len, bad);
3810 if (pool_ns_len > 0) { 3827 if (pool_ns_len > 0) {
3811 ceph_decode_need(&p, end, pool_ns_len, bad); 3828 ceph_decode_need(&p, end, pool_ns_len, bad);
3812 pool_ns = ceph_find_or_create_string(p, pool_ns_len); 3829 extra_info.pool_ns =
3830 ceph_find_or_create_string(p, pool_ns_len);
3813 p += pool_ns_len; 3831 p += pool_ns_len;
3814 } 3832 }
3815 } 3833 }
3816 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
3817 /* lookup ino */ 3854 /* lookup ino */
3818 inode = ceph_find_inode(sb, vino); 3855 inode = ceph_find_inode(mdsc->fsc->sb, vino);
3819 ci = ceph_inode(inode); 3856 ci = ceph_inode(inode);
3820 dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino, 3857 dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino,
3821 vino.snap, inode); 3858 vino.snap, inode);
@@ -3848,7 +3885,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3848 /* these will work even if we don't have a cap yet */ 3885 /* these will work even if we don't have a cap yet */
3849 switch (op) { 3886 switch (op) {
3850 case CEPH_CAP_OP_FLUSHSNAP_ACK: 3887 case CEPH_CAP_OP_FLUSHSNAP_ACK:
3851 handle_cap_flushsnap_ack(inode, tid, h, session); 3888 handle_cap_flushsnap_ack(inode, le64_to_cpu(msg->hdr.tid),
3889 h, session);
3852 goto done; 3890 goto done;
3853 3891
3854 case CEPH_CAP_OP_EXPORT: 3892 case CEPH_CAP_OP_EXPORT:
@@ -3867,10 +3905,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3867 down_read(&mdsc->snap_rwsem); 3905 down_read(&mdsc->snap_rwsem);
3868 } 3906 }
3869 handle_cap_import(mdsc, inode, h, peer, session, 3907 handle_cap_import(mdsc, inode, h, peer, session,
3870 &cap, &issued); 3908 &cap, &extra_info.issued);
3871 handle_cap_grant(mdsc, inode, h, &pool_ns, 3909 handle_cap_grant(inode, session, cap,
3872 inline_version, inline_data, inline_len, 3910 h, msg->middle, &extra_info);
3873 msg->middle, session, cap, issued);
3874 if (realm) 3911 if (realm)
3875 ceph_put_snap_realm(mdsc, realm); 3912 ceph_put_snap_realm(mdsc, realm);
3876 goto done_unlocked; 3913 goto done_unlocked;
@@ -3878,10 +3915,11 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3878 3915
3879 /* the rest require a cap */ 3916 /* the rest require a cap */
3880 spin_lock(&ci->i_ceph_lock); 3917 spin_lock(&ci->i_ceph_lock);
3881 cap = __get_cap_for_mds(ceph_inode(inode), mds); 3918 cap = __get_cap_for_mds(ceph_inode(inode), session->s_mds);
3882 if (!cap) { 3919 if (!cap) {
3883 dout(" no cap on %p ino %llx.%llx from mds%d\n", 3920 dout(" no cap on %p ino %llx.%llx from mds%d\n",
3884 inode, ceph_ino(inode), ceph_snap(inode), mds); 3921 inode, ceph_ino(inode), ceph_snap(inode),
3922 session->s_mds);
3885 spin_unlock(&ci->i_ceph_lock); 3923 spin_unlock(&ci->i_ceph_lock);
3886 goto flush_cap_releases; 3924 goto flush_cap_releases;
3887 } 3925 }
@@ -3890,15 +3928,15 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3890 switch (op) { 3928 switch (op) {
3891 case CEPH_CAP_OP_REVOKE: 3929 case CEPH_CAP_OP_REVOKE:
3892 case CEPH_CAP_OP_GRANT: 3930 case CEPH_CAP_OP_GRANT:
3893 __ceph_caps_issued(ci, &issued); 3931 __ceph_caps_issued(ci, &extra_info.issued);
3894 issued |= __ceph_caps_dirty(ci); 3932 extra_info.issued |= __ceph_caps_dirty(ci);
3895 handle_cap_grant(mdsc, inode, h, &pool_ns, 3933 handle_cap_grant(inode, session, cap,
3896 inline_version, inline_data, inline_len, 3934 h, msg->middle, &extra_info);
3897 msg->middle, session, cap, issued);
3898 goto done_unlocked; 3935 goto done_unlocked;
3899 3936
3900 case CEPH_CAP_OP_FLUSH_ACK: 3937 case CEPH_CAP_OP_FLUSH_ACK:
3901 handle_cap_flush_ack(inode, tid, h, session, cap); 3938 handle_cap_flush_ack(inode, le64_to_cpu(msg->hdr.tid),
3939 h, session, cap);
3902 break; 3940 break;
3903 3941
3904 case CEPH_CAP_OP_TRUNC: 3942 case CEPH_CAP_OP_TRUNC:
@@ -3925,7 +3963,7 @@ done:
3925 mutex_unlock(&session->s_mutex); 3963 mutex_unlock(&session->s_mutex);
3926done_unlocked: 3964done_unlocked:
3927 iput(inode); 3965 iput(inode);
3928 ceph_put_string(pool_ns); 3966 ceph_put_string(extra_info.pool_ns);
3929 return; 3967 return;
3930 3968
3931bad: 3969bad:
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 1a78dd6f8bf2..036ac0f3a393 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1486,6 +1486,8 @@ const struct file_operations ceph_dir_fops = {
1486 .release = ceph_release, 1486 .release = ceph_release,
1487 .unlocked_ioctl = ceph_ioctl, 1487 .unlocked_ioctl = ceph_ioctl,
1488 .fsync = ceph_fsync, 1488 .fsync = ceph_fsync,
1489 .lock = ceph_lock,
1490 .flock = ceph_flock,
1489}; 1491};
1490 1492
1491const struct file_operations ceph_snapdir_fops = { 1493const struct file_operations ceph_snapdir_fops = {
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index cf0e45b10121..6b9f7f3cd237 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -895,7 +895,6 @@ static void ceph_aio_retry_work(struct work_struct *work)
895 req->r_callback = ceph_aio_complete_req; 895 req->r_callback = ceph_aio_complete_req;
896 req->r_inode = inode; 896 req->r_inode = inode;
897 req->r_priv = aio_req; 897 req->r_priv = aio_req;
898 req->r_abort_on_full = true;
899 898
900 ret = ceph_osdc_start_request(req->r_osdc, req, false); 899 ret = ceph_osdc_start_request(req->r_osdc, req, false);
901out: 900out:
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index ae056927080d..4fda7a9d4c9d 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -739,7 +739,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
739 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; 739 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
740 struct ceph_mds_reply_inode *info = iinfo->in; 740 struct ceph_mds_reply_inode *info = iinfo->in;
741 struct ceph_inode_info *ci = ceph_inode(inode); 741 struct ceph_inode_info *ci = ceph_inode(inode);
742 int issued = 0, implemented, new_issued; 742 int issued, new_issued, info_caps;
743 struct timespec mtime, atime, ctime; 743 struct timespec mtime, atime, ctime;
744 struct ceph_buffer *xattr_blob = NULL; 744 struct ceph_buffer *xattr_blob = NULL;
745 struct ceph_string *pool_ns = NULL; 745 struct ceph_string *pool_ns = NULL;
@@ -754,8 +754,10 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
754 inode, ceph_vinop(inode), le64_to_cpu(info->version), 754 inode, ceph_vinop(inode), le64_to_cpu(info->version),
755 ci->i_version); 755 ci->i_version);
756 756
757 info_caps = le32_to_cpu(info->cap.caps);
758
757 /* prealloc new cap struct */ 759 /* prealloc new cap struct */
758 if (info->cap.caps && ceph_snap(inode) == CEPH_NOSNAP) 760 if (info_caps && ceph_snap(inode) == CEPH_NOSNAP)
759 new_cap = ceph_get_cap(mdsc, caps_reservation); 761 new_cap = ceph_get_cap(mdsc, caps_reservation);
760 762
761 /* 763 /*
@@ -792,9 +794,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
792 le64_to_cpu(info->version) > (ci->i_version & ~1))) 794 le64_to_cpu(info->version) > (ci->i_version & ~1)))
793 new_version = true; 795 new_version = true;
794 796
795 issued = __ceph_caps_issued(ci, &implemented); 797 __ceph_caps_issued(ci, &issued);
796 issued |= implemented | __ceph_caps_dirty(ci); 798 issued |= __ceph_caps_dirty(ci);
797 new_issued = ~issued & le32_to_cpu(info->cap.caps); 799 new_issued = ~issued & info_caps;
798 800
799 /* update inode */ 801 /* update inode */
800 inode->i_rdev = le32_to_cpu(info->rdev); 802 inode->i_rdev = le32_to_cpu(info->rdev);
@@ -826,6 +828,11 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
826 &ctime, &mtime, &atime); 828 &ctime, &mtime, &atime);
827 } 829 }
828 830
831 if (new_version || (info_caps & CEPH_CAP_FILE_SHARED)) {
832 ci->i_files = le64_to_cpu(info->files);
833 ci->i_subdirs = le64_to_cpu(info->subdirs);
834 }
835
829 if (new_version || 836 if (new_version ||
830 (new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) { 837 (new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) {
831 s64 old_pool = ci->i_layout.pool_id; 838 s64 old_pool = ci->i_layout.pool_id;
@@ -854,6 +861,18 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
854 } 861 }
855 } 862 }
856 863
864 /* layout and rstat are not tracked by capability, update them if
865 * the inode info is from auth mds */
866 if (new_version || (info->cap.flags & CEPH_CAP_FLAG_AUTH)) {
867 if (S_ISDIR(inode->i_mode)) {
868 ci->i_dir_layout = iinfo->dir_layout;
869 ci->i_rbytes = le64_to_cpu(info->rbytes);
870 ci->i_rfiles = le64_to_cpu(info->rfiles);
871 ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
872 ceph_decode_timespec(&ci->i_rctime, &info->rctime);
873 }
874 }
875
857 /* xattrs */ 876 /* xattrs */
858 /* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */ 877 /* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */
859 if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) && 878 if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) &&
@@ -870,7 +889,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
870 } 889 }
871 890
872 /* finally update i_version */ 891 /* finally update i_version */
873 ci->i_version = le64_to_cpu(info->version); 892 if (le64_to_cpu(info->version) > ci->i_version)
893 ci->i_version = le64_to_cpu(info->version);
874 894
875 inode->i_mapping->a_ops = &ceph_aops; 895 inode->i_mapping->a_ops = &ceph_aops;
876 896
@@ -918,15 +938,6 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
918 case S_IFDIR: 938 case S_IFDIR:
919 inode->i_op = &ceph_dir_iops; 939 inode->i_op = &ceph_dir_iops;
920 inode->i_fop = &ceph_dir_fops; 940 inode->i_fop = &ceph_dir_fops;
921
922 ci->i_dir_layout = iinfo->dir_layout;
923
924 ci->i_files = le64_to_cpu(info->files);
925 ci->i_subdirs = le64_to_cpu(info->subdirs);
926 ci->i_rbytes = le64_to_cpu(info->rbytes);
927 ci->i_rfiles = le64_to_cpu(info->rfiles);
928 ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
929 ceph_decode_timespec(&ci->i_rctime, &info->rctime);
930 break; 941 break;
931 default: 942 default:
932 pr_err("fill_inode %llx.%llx BAD mode 0%o\n", 943 pr_err("fill_inode %llx.%llx BAD mode 0%o\n",
@@ -934,12 +945,11 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
934 } 945 }
935 946
936 /* were we issued a capability? */ 947 /* were we issued a capability? */
937 if (info->cap.caps) { 948 if (info_caps) {
938 if (ceph_snap(inode) == CEPH_NOSNAP) { 949 if (ceph_snap(inode) == CEPH_NOSNAP) {
939 unsigned caps = le32_to_cpu(info->cap.caps);
940 ceph_add_cap(inode, session, 950 ceph_add_cap(inode, session,
941 le64_to_cpu(info->cap.cap_id), 951 le64_to_cpu(info->cap.cap_id),
942 cap_fmode, caps, 952 cap_fmode, info_caps,
943 le32_to_cpu(info->cap.wanted), 953 le32_to_cpu(info->cap.wanted),
944 le32_to_cpu(info->cap.seq), 954 le32_to_cpu(info->cap.seq),
945 le32_to_cpu(info->cap.mseq), 955 le32_to_cpu(info->cap.mseq),
@@ -949,7 +959,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
949 /* set dir completion flag? */ 959 /* set dir completion flag? */
950 if (S_ISDIR(inode->i_mode) && 960 if (S_ISDIR(inode->i_mode) &&
951 ci->i_files == 0 && ci->i_subdirs == 0 && 961 ci->i_files == 0 && ci->i_subdirs == 0 &&
952 (caps & CEPH_CAP_FILE_SHARED) && 962 (info_caps & CEPH_CAP_FILE_SHARED) &&
953 (issued & CEPH_CAP_FILE_EXCL) == 0 && 963 (issued & CEPH_CAP_FILE_EXCL) == 0 &&
954 !__ceph_dir_is_complete(ci)) { 964 !__ceph_dir_is_complete(ci)) {
955 dout(" marking %p complete (empty)\n", inode); 965 dout(" marking %p complete (empty)\n", inode);
@@ -962,8 +972,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
962 wake = true; 972 wake = true;
963 } else { 973 } else {
964 dout(" %p got snap_caps %s\n", inode, 974 dout(" %p got snap_caps %s\n", inode,
965 ceph_cap_string(le32_to_cpu(info->cap.caps))); 975 ceph_cap_string(info_caps));
966 ci->i_snap_caps |= le32_to_cpu(info->cap.caps); 976 ci->i_snap_caps |= info_caps;
967 if (cap_fmode >= 0) 977 if (cap_fmode >= 0)
968 __ceph_get_fmode(ci, cap_fmode); 978 __ceph_get_fmode(ci, cap_fmode);
969 } 979 }
@@ -978,8 +988,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
978 int cache_caps = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO; 988 int cache_caps = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
979 ci->i_inline_version = iinfo->inline_version; 989 ci->i_inline_version = iinfo->inline_version;
980 if (ci->i_inline_version != CEPH_INLINE_NONE && 990 if (ci->i_inline_version != CEPH_INLINE_NONE &&
981 (locked_page || 991 (locked_page || (info_caps & cache_caps)))
982 (le32_to_cpu(info->cap.caps) & cache_caps)))
983 fill_inline = true; 992 fill_inline = true;
984 } 993 }
985 994
@@ -2178,6 +2187,7 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
2178 struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); 2187 struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
2179 struct ceph_mds_client *mdsc = fsc->mdsc; 2188 struct ceph_mds_client *mdsc = fsc->mdsc;
2180 struct ceph_mds_request *req; 2189 struct ceph_mds_request *req;
2190 int mode;
2181 int err; 2191 int err;
2182 2192
2183 if (ceph_snap(inode) == CEPH_SNAPDIR) { 2193 if (ceph_snap(inode) == CEPH_SNAPDIR) {
@@ -2190,7 +2200,8 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
2190 if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1)) 2200 if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
2191 return 0; 2201 return 0;
2192 2202
2193 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS); 2203 mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS;
2204 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode);
2194 if (IS_ERR(req)) 2205 if (IS_ERR(req))
2195 return PTR_ERR(req); 2206 return PTR_ERR(req);
2196 req->r_inode = inode; 2207 req->r_inode = inode;
@@ -2261,6 +2272,14 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
2261 stat->size = ci->i_files + ci->i_subdirs; 2272 stat->size = ci->i_files + ci->i_subdirs;
2262 stat->blocks = 0; 2273 stat->blocks = 0;
2263 stat->blksize = 65536; 2274 stat->blksize = 65536;
2275 /*
2276 * Some applications rely on the number of st_nlink
2277 * value on directories to be either 0 (if unlinked)
2278 * or 2 + number of subdirectories.
2279 */
2280 if (stat->nlink == 1)
2281 /* '.' + '..' + subdirs */
2282 stat->nlink = 1 + 1 + ci->i_subdirs;
2264 } 2283 }
2265 } 2284 }
2266 return err; 2285 return err;
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index b33082e6878f..95a3b3ac9b6e 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -45,7 +45,7 @@ static void ceph_put_super(struct super_block *s)
45static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) 45static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
46{ 46{
47 struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry)); 47 struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
48 struct ceph_monmap *monmap = fsc->client->monc.monmap; 48 struct ceph_mon_client *monc = &fsc->client->monc;
49 struct ceph_statfs st; 49 struct ceph_statfs st;
50 u64 fsid; 50 u64 fsid;
51 int err; 51 int err;
@@ -58,7 +58,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
58 } 58 }
59 59
60 dout("statfs\n"); 60 dout("statfs\n");
61 err = ceph_monc_do_statfs(&fsc->client->monc, data_pool, &st); 61 err = ceph_monc_do_statfs(monc, data_pool, &st);
62 if (err < 0) 62 if (err < 0)
63 return err; 63 return err;
64 64
@@ -94,8 +94,11 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
94 buf->f_namelen = NAME_MAX; 94 buf->f_namelen = NAME_MAX;
95 95
96 /* Must convert the fsid, for consistent values across arches */ 96 /* Must convert the fsid, for consistent values across arches */
97 fsid = le64_to_cpu(*(__le64 *)(&monmap->fsid)) ^ 97 mutex_lock(&monc->mutex);
98 le64_to_cpu(*((__le64 *)&monmap->fsid + 1)); 98 fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^
99 le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1));
100 mutex_unlock(&monc->mutex);
101
99 buf->f_fsid.val[0] = fsid & 0xffffffff; 102 buf->f_fsid.val[0] = fsid & 0xffffffff;
100 buf->f_fsid.val[1] = fsid >> 32; 103 buf->f_fsid.val[1] = fsid >> 32;
101 104
@@ -256,19 +259,19 @@ static int parse_fsopt_token(char *c, void *private)
256 break; 259 break;
257 /* misc */ 260 /* misc */
258 case Opt_wsize: 261 case Opt_wsize:
259 if (intval < PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE) 262 if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
260 return -EINVAL; 263 return -EINVAL;
261 fsopt->wsize = ALIGN(intval, PAGE_SIZE); 264 fsopt->wsize = ALIGN(intval, PAGE_SIZE);
262 break; 265 break;
263 case Opt_rsize: 266 case Opt_rsize:
264 if (intval < PAGE_SIZE || intval > CEPH_MAX_READ_SIZE) 267 if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_READ_SIZE)
265 return -EINVAL; 268 return -EINVAL;
266 fsopt->rsize = ALIGN(intval, PAGE_SIZE); 269 fsopt->rsize = ALIGN(intval, PAGE_SIZE);
267 break; 270 break;
268 case Opt_rasize: 271 case Opt_rasize:
269 if (intval < 0) 272 if (intval < 0)
270 return -EINVAL; 273 return -EINVAL;
271 fsopt->rasize = ALIGN(intval + PAGE_SIZE - 1, PAGE_SIZE); 274 fsopt->rasize = ALIGN(intval, PAGE_SIZE);
272 break; 275 break;
273 case Opt_caps_wanted_delay_min: 276 case Opt_caps_wanted_delay_min:
274 if (intval < 1) 277 if (intval < 1)
@@ -286,7 +289,7 @@ static int parse_fsopt_token(char *c, void *private)
286 fsopt->max_readdir = intval; 289 fsopt->max_readdir = intval;
287 break; 290 break;
288 case Opt_readdir_max_bytes: 291 case Opt_readdir_max_bytes:
289 if (intval < PAGE_SIZE && intval != 0) 292 if (intval < (int)PAGE_SIZE && intval != 0)
290 return -EINVAL; 293 return -EINVAL;
291 fsopt->max_readdir_bytes = intval; 294 fsopt->max_readdir_bytes = intval;
292 break; 295 break;
@@ -534,6 +537,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
534 seq_puts(m, ",noasyncreaddir"); 537 seq_puts(m, ",noasyncreaddir");
535 if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0) 538 if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0)
536 seq_puts(m, ",nodcache"); 539 seq_puts(m, ",nodcache");
540 if (fsopt->flags & CEPH_MOUNT_OPT_INO32)
541 seq_puts(m, ",ino32");
537 if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE) { 542 if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE) {
538 seq_show_option(m, "fsc", fsopt->fscache_uniq); 543 seq_show_option(m, "fsc", fsopt->fscache_uniq);
539 } 544 }
@@ -551,7 +556,7 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
551 556
552 if (fsopt->mds_namespace) 557 if (fsopt->mds_namespace)
553 seq_show_option(m, "mds_namespace", fsopt->mds_namespace); 558 seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
554 if (fsopt->wsize) 559 if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
555 seq_printf(m, ",wsize=%d", fsopt->wsize); 560 seq_printf(m, ",wsize=%d", fsopt->wsize);
556 if (fsopt->rsize != CEPH_MAX_READ_SIZE) 561 if (fsopt->rsize != CEPH_MAX_READ_SIZE)
557 seq_printf(m, ",rsize=%d", fsopt->rsize); 562 seq_printf(m, ",rsize=%d", fsopt->rsize);
@@ -616,7 +621,9 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
616 err = PTR_ERR(fsc->client); 621 err = PTR_ERR(fsc->client);
617 goto fail; 622 goto fail;
618 } 623 }
624
619 fsc->client->extra_mon_dispatch = extra_mon_dispatch; 625 fsc->client->extra_mon_dispatch = extra_mon_dispatch;
626 fsc->client->osdc.abort_on_full = true;
620 627
621 if (!fsopt->mds_namespace) { 628 if (!fsopt->mds_namespace) {
622 ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP, 629 ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP,
@@ -674,6 +681,13 @@ fail:
674 return ERR_PTR(err); 681 return ERR_PTR(err);
675} 682}
676 683
684static void flush_fs_workqueues(struct ceph_fs_client *fsc)
685{
686 flush_workqueue(fsc->wb_wq);
687 flush_workqueue(fsc->pg_inv_wq);
688 flush_workqueue(fsc->trunc_wq);
689}
690
677static void destroy_fs_client(struct ceph_fs_client *fsc) 691static void destroy_fs_client(struct ceph_fs_client *fsc)
678{ 692{
679 dout("destroy_fs_client %p\n", fsc); 693 dout("destroy_fs_client %p\n", fsc);
@@ -793,6 +807,7 @@ static void ceph_umount_begin(struct super_block *sb)
793 if (!fsc) 807 if (!fsc)
794 return; 808 return;
795 fsc->mount_state = CEPH_MOUNT_SHUTDOWN; 809 fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
810 ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
796 ceph_mdsc_force_umount(fsc->mdsc); 811 ceph_mdsc_force_umount(fsc->mdsc);
797 return; 812 return;
798} 813}
@@ -1088,6 +1103,8 @@ static void ceph_kill_sb(struct super_block *s)
1088 dout("kill_sb %p\n", s); 1103 dout("kill_sb %p\n", s);
1089 1104
1090 ceph_mdsc_pre_umount(fsc->mdsc); 1105 ceph_mdsc_pre_umount(fsc->mdsc);
1106 flush_fs_workqueues(fsc);
1107
1091 generic_shutdown_super(s); 1108 generic_shutdown_super(s);
1092 1109
1093 fsc->client->extra_mon_dispatch = NULL; 1110 fsc->client->extra_mon_dispatch = NULL;
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 315f7e63e7cc..5bc8edb4c2a6 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -50,10 +50,14 @@ struct ceph_vxattr {
50 size_t name_size; /* strlen(name) + 1 (for '\0') */ 50 size_t name_size; /* strlen(name) + 1 (for '\0') */
51 size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val, 51 size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
52 size_t size); 52 size_t size);
53 bool readonly, hidden;
54 bool (*exists_cb)(struct ceph_inode_info *ci); 53 bool (*exists_cb)(struct ceph_inode_info *ci);
54 unsigned int flags;
55}; 55};
56 56
57#define VXATTR_FLAG_READONLY (1<<0)
58#define VXATTR_FLAG_HIDDEN (1<<1)
59#define VXATTR_FLAG_RSTAT (1<<2)
60
57/* layouts */ 61/* layouts */
58 62
59static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci) 63static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)
@@ -262,32 +266,31 @@ static size_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
262#define CEPH_XATTR_NAME2(_type, _name, _name2) \ 266#define CEPH_XATTR_NAME2(_type, _name, _name2) \
263 XATTR_CEPH_PREFIX #_type "." #_name "." #_name2 267 XATTR_CEPH_PREFIX #_type "." #_name "." #_name2
264 268
265#define XATTR_NAME_CEPH(_type, _name) \ 269#define XATTR_NAME_CEPH(_type, _name, _flags) \
266 { \ 270 { \
267 .name = CEPH_XATTR_NAME(_type, _name), \ 271 .name = CEPH_XATTR_NAME(_type, _name), \
268 .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \ 272 .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
269 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \ 273 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
270 .readonly = true, \ 274 .exists_cb = NULL, \
271 .hidden = false, \ 275 .flags = (VXATTR_FLAG_READONLY | _flags), \
272 .exists_cb = NULL, \
273 } 276 }
277#define XATTR_RSTAT_FIELD(_type, _name) \
278 XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
274#define XATTR_LAYOUT_FIELD(_type, _name, _field) \ 279#define XATTR_LAYOUT_FIELD(_type, _name, _field) \
275 { \ 280 { \
276 .name = CEPH_XATTR_NAME2(_type, _name, _field), \ 281 .name = CEPH_XATTR_NAME2(_type, _name, _field), \
277 .name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \ 282 .name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \
278 .getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \ 283 .getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \
279 .readonly = false, \
280 .hidden = true, \
281 .exists_cb = ceph_vxattrcb_layout_exists, \ 284 .exists_cb = ceph_vxattrcb_layout_exists, \
285 .flags = VXATTR_FLAG_HIDDEN, \
282 } 286 }
283#define XATTR_QUOTA_FIELD(_type, _name) \ 287#define XATTR_QUOTA_FIELD(_type, _name) \
284 { \ 288 { \
285 .name = CEPH_XATTR_NAME(_type, _name), \ 289 .name = CEPH_XATTR_NAME(_type, _name), \
286 .name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \ 290 .name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \
287 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \ 291 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
288 .readonly = false, \
289 .hidden = true, \
290 .exists_cb = ceph_vxattrcb_quota_exists, \ 292 .exists_cb = ceph_vxattrcb_quota_exists, \
293 .flags = VXATTR_FLAG_HIDDEN, \
291 } 294 }
292 295
293static struct ceph_vxattr ceph_dir_vxattrs[] = { 296static struct ceph_vxattr ceph_dir_vxattrs[] = {
@@ -295,30 +298,28 @@ static struct ceph_vxattr ceph_dir_vxattrs[] = {
295 .name = "ceph.dir.layout", 298 .name = "ceph.dir.layout",
296 .name_size = sizeof("ceph.dir.layout"), 299 .name_size = sizeof("ceph.dir.layout"),
297 .getxattr_cb = ceph_vxattrcb_layout, 300 .getxattr_cb = ceph_vxattrcb_layout,
298 .readonly = false,
299 .hidden = true,
300 .exists_cb = ceph_vxattrcb_layout_exists, 301 .exists_cb = ceph_vxattrcb_layout_exists,
302 .flags = VXATTR_FLAG_HIDDEN,
301 }, 303 },
302 XATTR_LAYOUT_FIELD(dir, layout, stripe_unit), 304 XATTR_LAYOUT_FIELD(dir, layout, stripe_unit),
303 XATTR_LAYOUT_FIELD(dir, layout, stripe_count), 305 XATTR_LAYOUT_FIELD(dir, layout, stripe_count),
304 XATTR_LAYOUT_FIELD(dir, layout, object_size), 306 XATTR_LAYOUT_FIELD(dir, layout, object_size),
305 XATTR_LAYOUT_FIELD(dir, layout, pool), 307 XATTR_LAYOUT_FIELD(dir, layout, pool),
306 XATTR_LAYOUT_FIELD(dir, layout, pool_namespace), 308 XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
307 XATTR_NAME_CEPH(dir, entries), 309 XATTR_NAME_CEPH(dir, entries, 0),
308 XATTR_NAME_CEPH(dir, files), 310 XATTR_NAME_CEPH(dir, files, 0),
309 XATTR_NAME_CEPH(dir, subdirs), 311 XATTR_NAME_CEPH(dir, subdirs, 0),
310 XATTR_NAME_CEPH(dir, rentries), 312 XATTR_RSTAT_FIELD(dir, rentries),
311 XATTR_NAME_CEPH(dir, rfiles), 313 XATTR_RSTAT_FIELD(dir, rfiles),
312 XATTR_NAME_CEPH(dir, rsubdirs), 314 XATTR_RSTAT_FIELD(dir, rsubdirs),
313 XATTR_NAME_CEPH(dir, rbytes), 315 XATTR_RSTAT_FIELD(dir, rbytes),
314 XATTR_NAME_CEPH(dir, rctime), 316 XATTR_RSTAT_FIELD(dir, rctime),
315 { 317 {
316 .name = "ceph.quota", 318 .name = "ceph.quota",
317 .name_size = sizeof("ceph.quota"), 319 .name_size = sizeof("ceph.quota"),
318 .getxattr_cb = ceph_vxattrcb_quota, 320 .getxattr_cb = ceph_vxattrcb_quota,
319 .readonly = false,
320 .hidden = true,
321 .exists_cb = ceph_vxattrcb_quota_exists, 321 .exists_cb = ceph_vxattrcb_quota_exists,
322 .flags = VXATTR_FLAG_HIDDEN,
322 }, 323 },
323 XATTR_QUOTA_FIELD(quota, max_bytes), 324 XATTR_QUOTA_FIELD(quota, max_bytes),
324 XATTR_QUOTA_FIELD(quota, max_files), 325 XATTR_QUOTA_FIELD(quota, max_files),
@@ -333,9 +334,8 @@ static struct ceph_vxattr ceph_file_vxattrs[] = {
333 .name = "ceph.file.layout", 334 .name = "ceph.file.layout",
334 .name_size = sizeof("ceph.file.layout"), 335 .name_size = sizeof("ceph.file.layout"),
335 .getxattr_cb = ceph_vxattrcb_layout, 336 .getxattr_cb = ceph_vxattrcb_layout,
336 .readonly = false,
337 .hidden = true,
338 .exists_cb = ceph_vxattrcb_layout_exists, 337 .exists_cb = ceph_vxattrcb_layout_exists,
338 .flags = VXATTR_FLAG_HIDDEN,
339 }, 339 },
340 XATTR_LAYOUT_FIELD(file, layout, stripe_unit), 340 XATTR_LAYOUT_FIELD(file, layout, stripe_unit),
341 XATTR_LAYOUT_FIELD(file, layout, stripe_count), 341 XATTR_LAYOUT_FIELD(file, layout, stripe_count),
@@ -374,9 +374,10 @@ static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs)
374 struct ceph_vxattr *vxattr; 374 struct ceph_vxattr *vxattr;
375 size_t size = 0; 375 size_t size = 0;
376 376
377 for (vxattr = vxattrs; vxattr->name; vxattr++) 377 for (vxattr = vxattrs; vxattr->name; vxattr++) {
378 if (!vxattr->hidden) 378 if (!(vxattr->flags & VXATTR_FLAG_HIDDEN))
379 size += vxattr->name_size; 379 size += vxattr->name_size;
380 }
380 381
381 return size; 382 return size;
382} 383}
@@ -809,7 +810,10 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
809 /* let's see if a virtual xattr was requested */ 810 /* let's see if a virtual xattr was requested */
810 vxattr = ceph_match_vxattr(inode, name); 811 vxattr = ceph_match_vxattr(inode, name);
811 if (vxattr) { 812 if (vxattr) {
812 err = ceph_do_getattr(inode, 0, true); 813 int mask = 0;
814 if (vxattr->flags & VXATTR_FLAG_RSTAT)
815 mask |= CEPH_STAT_RSTAT;
816 err = ceph_do_getattr(inode, mask, true);
813 if (err) 817 if (err)
814 return err; 818 return err;
815 err = -ENODATA; 819 err = -ENODATA;
@@ -919,7 +923,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
919 err = namelen; 923 err = namelen;
920 if (vxattrs) { 924 if (vxattrs) {
921 for (i = 0; vxattrs[i].name; i++) { 925 for (i = 0; vxattrs[i].name; i++) {
922 if (!vxattrs[i].hidden && 926 if (!(vxattrs[i].flags & VXATTR_FLAG_HIDDEN) &&
923 !(vxattrs[i].exists_cb && 927 !(vxattrs[i].exists_cb &&
924 !vxattrs[i].exists_cb(ci))) { 928 !vxattrs[i].exists_cb(ci))) {
925 len = sprintf(names, "%s", vxattrs[i].name); 929 len = sprintf(names, "%s", vxattrs[i].name);
@@ -1024,7 +1028,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
1024 1028
1025 vxattr = ceph_match_vxattr(inode, name); 1029 vxattr = ceph_match_vxattr(inode, name);
1026 if (vxattr) { 1030 if (vxattr) {
1027 if (vxattr->readonly) 1031 if (vxattr->flags & VXATTR_FLAG_READONLY)
1028 return -EOPNOTSUPP; 1032 return -EOPNOTSUPP;
1029 if (value && !strncmp(vxattr->name, "ceph.quota", 10)) 1033 if (value && !strncmp(vxattr->name, "ceph.quota", 10))
1030 check_realm = true; 1034 check_realm = true;