tree: https://github.com/ceph/ceph-client.git testing head: 9fda3b75534bb1b1c9330b65a5814d8e1dc1c688 commit: 6dfc4c69796afbff11709c98c3ef4a94c62b2ac8 [4/5] ceph: define argument structure for handle_cap_grant reproduce: # apt-get install sparse git checkout 6dfc4c69796afbff11709c98c3ef4a94c62b2ac8 make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) >> fs/ceph/caps.c:3170:42: sparse: incompatible types in comparison expression (different address spaces) fs/ceph/caps.c:3293:9: sparse: context imbalance in 'handle_cap_grant' - wrong count at exit fs/ceph/caps.c:3882:17: sparse: context imbalance in 'ceph_handle_caps' - unexpected unlock vim +3170 fs/ceph/caps.c 3038 3039 /* 3040 * Handle a cap GRANT message from the MDS. (Note that a GRANT may 3041 * actually be a revocation if it specifies a smaller cap set.) 3042 * 3043 * caller holds s_mutex and i_ceph_lock, we drop both. 3044 */ 3045 static void handle_cap_grant(struct inode *inode, 3046 struct ceph_mds_session *session, 3047 struct ceph_cap *cap, 3048 struct ceph_mds_caps *grant, 3049 struct ceph_buffer *xattr_buf, 3050 struct cap_extra_info *extra_info) 3051 __releases(ci->i_ceph_lock) 3052 __releases(sesson->s_mdsc->snap_rwsem) 3053 { 3054 struct ceph_inode_info *ci = ceph_inode(inode); 3055 int seq = le32_to_cpu(grant->seq); 3056 int newcaps = le32_to_cpu(grant->caps); 3057 int used, wanted, dirty; 3058 u64 size = le64_to_cpu(grant->size); 3059 u64 max_size = le64_to_cpu(grant->max_size); 3060 struct timespec mtime, atime, ctime; 3061 int check_caps = 0; 3062 bool wake = false; 3063 bool writeback = false; 3064 bool queue_trunc = false; 3065 bool queue_invalidate = false; 3066 bool deleted_inode = false; 3067 bool fill_inline = false; 3068 3069 dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", 3070 inode, cap, session->s_mds, seq, ceph_cap_string(newcaps)); 3071 dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, 3072 inode->i_size); 3073 3074 3075 /* 3076 * auth mds of the inode changed. we received the cap export message, 3077 * but still haven't received the cap import message. handle_cap_export 3078 * updated the new auth MDS' cap. 3079 * 3080 * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing a message 3081 * that was sent before the cap import message. So don't remove caps. 3082 */ 3083 if (ceph_seq_cmp(seq, cap->seq) <= 0) { 3084 WARN_ON(cap != ci->i_auth_cap); 3085 WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id)); 3086 seq = cap->seq; 3087 newcaps |= cap->issued; 3088 } 3089 3090 /* 3091 * If CACHE is being revoked, and we have no dirty buffers, 3092 * try to invalidate (once). (If there are dirty buffers, we 3093 * will invalidate _after_ writeback.) 3094 */ 3095 if (!S_ISDIR(inode->i_mode) && /* don't invalidate readdir cache */ 3096 ((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) && 3097 (newcaps & CEPH_CAP_FILE_LAZYIO) == 0 && 3098 !(ci->i_wrbuffer_ref || ci->i_wb_ref)) { 3099 if (try_nonblocking_invalidate(inode)) { 3100 /* there were locked pages.. invalidate later 3101 in a separate thread. */ 3102 if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { 3103 queue_invalidate = true; 3104 ci->i_rdcache_revoking = ci->i_rdcache_gen; 3105 } 3106 } 3107 } 3108 3109 /* side effects now are allowed */ 3110 cap->cap_gen = session->s_cap_gen; 3111 cap->seq = seq; 3112 3113 __check_cap_issue(ci, cap, newcaps); 3114 3115 if ((newcaps & CEPH_CAP_AUTH_SHARED) && 3116 (extra_info->issued & CEPH_CAP_AUTH_EXCL) == 0) { 3117 inode->i_mode = le32_to_cpu(grant->mode); 3118 inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid)); 3119 inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid)); 3120 dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode, 3121 from_kuid(&init_user_ns, inode->i_uid), 3122 from_kgid(&init_user_ns, inode->i_gid)); 3123 } 3124 3125 if ((newcaps & CEPH_CAP_AUTH_SHARED) && 3126 (extra_info->issued & CEPH_CAP_LINK_EXCL) == 0) { 3127 set_nlink(inode, le32_to_cpu(grant->nlink)); 3128 if (inode->i_nlink == 0 && 3129 (newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL))) 3130 deleted_inode = true; 3131 } 3132 3133 if ((extra_info->issued & CEPH_CAP_XATTR_EXCL) == 0 && 3134 grant->xattr_len) { 3135 int len = le32_to_cpu(grant->xattr_len); 3136 u64 version = le64_to_cpu(grant->xattr_version); 3137 3138 if (version > ci->i_xattrs.version) { 3139 dout(" got new xattrs v%llu on %p len %d\n", 3140 version, inode, len); 3141 if (ci->i_xattrs.blob) 3142 ceph_buffer_put(ci->i_xattrs.blob); 3143 ci->i_xattrs.blob = ceph_buffer_get(xattr_buf); 3144 ci->i_xattrs.version = version; 3145 ceph_forget_all_cached_acls(inode); 3146 } 3147 } 3148 3149 if (newcaps & CEPH_CAP_ANY_RD) { 3150 /* ctime/mtime/atime? */ 3151 ceph_decode_timespec(&mtime, &grant->mtime); 3152 ceph_decode_timespec(&atime, &grant->atime); 3153 ceph_decode_timespec(&ctime, &grant->ctime); 3154 ceph_fill_file_time(inode, extra_info->issued, 3155 le32_to_cpu(grant->time_warp_seq), 3156 &ctime, &mtime, &atime); 3157 } 3158 3159 if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) { 3160 /* file layout may have changed */ 3161 s64 old_pool = ci->i_layout.pool_id; 3162 struct ceph_string *old_ns; 3163 3164 ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout); 3165 old_ns = rcu_dereference_protected(ci->i_layout.pool_ns, 3166 lockdep_is_held(&ci->i_ceph_lock)); 3167 rcu_assign_pointer(ci->i_layout.pool_ns, extra_info->pool_ns); 3168 3169 if (ci->i_layout.pool_id != old_pool || > 3170 ci->i_layout.pool_ns != old_ns) 3171 ci->i_ceph_flags &= ~CEPH_I_POOL_PERM; 3172 3173 extra_info->pool_ns = old_ns; 3174 3175 /* size/truncate_seq? */ 3176 queue_trunc = ceph_fill_file_size(inode, extra_info->issued, 3177 le32_to_cpu(grant->truncate_seq), 3178 le64_to_cpu(grant->truncate_size), 3179 size); 3180 } 3181 3182 if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) { 3183 if (max_size != ci->i_max_size) { 3184 dout("max_size %lld -> %llu\n", 3185 ci->i_max_size, max_size); 3186 ci->i_max_size = max_size; 3187 if (max_size >= ci->i_wanted_max_size) { 3188 ci->i_wanted_max_size = 0; /* reset */ 3189 ci->i_requested_max_size = 0; 3190 } 3191 wake = true; 3192 } else if (ci->i_wanted_max_size > ci->i_max_size && 3193 ci->i_wanted_max_size > ci->i_requested_max_size) { 3194 /* CEPH_CAP_OP_IMPORT */ 3195 wake = true; 3196 } 3197 } 3198 3199 /* check cap bits */ 3200 wanted = __ceph_caps_wanted(ci); 3201 used = __ceph_caps_used(ci); 3202 dirty = __ceph_caps_dirty(ci); 3203 dout(" my wanted = %s, used = %s, dirty %s\n", 3204 ceph_cap_string(wanted), 3205 ceph_cap_string(used), 3206 ceph_cap_string(dirty)); 3207 if (wanted != le32_to_cpu(grant->wanted)) { 3208 dout("mds wanted %s -> %s\n", 3209 ceph_cap_string(le32_to_cpu(grant->wanted)), 3210 ceph_cap_string(wanted)); 3211 /* imported cap may not have correct mds_wanted */ 3212 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) 3213 check_caps = 1; 3214 } 3215 3216 /* revocation, grant, or no-op? */ 3217 if (cap->issued & ~newcaps) { 3218 int revoking = cap->issued & ~newcaps; 3219 3220 dout("revocation: %s -> %s (revoking %s)\n", 3221 ceph_cap_string(cap->issued), 3222 ceph_cap_string(newcaps), 3223 ceph_cap_string(revoking)); 3224 if (revoking & used & CEPH_CAP_FILE_BUFFER) 3225 writeback = true; /* initiate writeback; will delay ack */ 3226 else if (revoking == CEPH_CAP_FILE_CACHE && 3227 (newcaps & CEPH_CAP_FILE_LAZYIO) == 0 && 3228 queue_invalidate) 3229 ; /* do nothing yet, invalidation will be queued */ 3230 else if (cap == ci->i_auth_cap) 3231 check_caps = 1; /* check auth cap only */ 3232 else 3233 check_caps = 2; /* check all caps */ 3234 cap->issued = newcaps; 3235 cap->implemented |= newcaps; 3236 } else if (cap->issued == newcaps) { 3237 dout("caps unchanged: %s -> %s\n", 3238 ceph_cap_string(cap->issued), ceph_cap_string(newcaps)); 3239 } else { 3240 dout("grant: %s -> %s\n", ceph_cap_string(cap->issued), 3241 ceph_cap_string(newcaps)); 3242 /* non-auth MDS is revoking the newly grant caps ? */ 3243 if (cap == ci->i_auth_cap && 3244 __ceph_caps_revoking_other(ci, cap, newcaps)) 3245 check_caps = 2; 3246 3247 cap->issued = newcaps; 3248 cap->implemented |= newcaps; /* add bits only, to 3249 * avoid stepping on a 3250 * pending revocation */ 3251 wake = true; 3252 } 3253 BUG_ON(cap->issued & ~cap->implemented); 3254 3255 if (extra_info->inline_version > 0 && 3256 extra_info->inline_version >= ci->i_inline_version) { 3257 ci->i_inline_version = extra_info->inline_version; 3258 if (ci->i_inline_version != CEPH_INLINE_NONE && 3259 (newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO))) 3260 fill_inline = true; 3261 } 3262 3263 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { 3264 if (newcaps & ~extra_info->issued) 3265 wake = true; 3266 kick_flushing_inode_caps(session->s_mdsc, session, inode); 3267 up_read(&session->s_mdsc->snap_rwsem); 3268 } else { 3269 spin_unlock(&ci->i_ceph_lock); 3270 } 3271 3272 if (fill_inline) 3273 ceph_fill_inline_data(inode, NULL, extra_info->inline_data, 3274 extra_info->inline_len); 3275 3276 if (queue_trunc) 3277 ceph_queue_vmtruncate(inode); 3278 3279 if (writeback) 3280 /* 3281 * queue inode for writeback: we can't actually call 3282 * filemap_write_and_wait, etc. from message handler 3283 * context. 3284 */ 3285 ceph_queue_writeback(inode); 3286 if (queue_invalidate) 3287 ceph_queue_invalidate(inode); 3288 if (deleted_inode) 3289 invalidate_aliases(inode); 3290 if (wake) 3291 wake_up_all(&ci->i_cap_wq); 3292 3293 if (check_caps == 1) 3294 ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY, 3295 session); 3296 else if (check_caps == 2) 3297 ceph_check_caps(ci, CHECK_CAPS_NODELAY, session); 3298 else 3299 mutex_unlock(&session->s_mutex); 3300 } 3301 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation -- To unsubscribe from this list: send the line "unsubscribe ceph-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html