summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2019-06-20 00:09:08 -0400
committerIlya Dryomov <idryomov@gmail.com>2019-07-08 08:01:44 -0400
commit49ada6e8dc9f64ad1e8dd6f7b453c9e584e9f897 (patch)
tree2a0441ae082748a0ba0a976ca30608037dc1d180 /fs/ceph/caps.c
parentd6cee9dbd8c841795cd672b98069866789916648 (diff)
ceph: more precise CEPH_CLIENT_CAPS_PENDING_CAPSNAP
Client uses this flag to tell mds if there is more cap snap need to flush. It's mainly for the case that client needs to re-send cap/snap flushes after mds failover, but CEPH_CAP_ANY_FILE_WR on corresponding inodes are all released before mds failover. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index f9055cdec3c7..d98dcd976c80 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1295,7 +1295,7 @@ void __ceph_remove_caps(struct ceph_inode_info *ci)
1295 * caller should hold snap_rwsem (read), s_mutex. 1295 * caller should hold snap_rwsem (read), s_mutex.
1296 */ 1296 */
1297static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, 1297static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
1298 int op, bool sync, int used, int want, int retain, 1298 int op, int flags, int used, int want, int retain,
1299 int flushing, u64 flush_tid, u64 oldest_flush_tid) 1299 int flushing, u64 flush_tid, u64 oldest_flush_tid)
1300 __releases(cap->ci->i_ceph_lock) 1300 __releases(cap->ci->i_ceph_lock)
1301{ 1301{
@@ -1393,12 +1393,19 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
1393 arg.mode = inode->i_mode; 1393 arg.mode = inode->i_mode;
1394 1394
1395 arg.inline_data = ci->i_inline_version != CEPH_INLINE_NONE; 1395 arg.inline_data = ci->i_inline_version != CEPH_INLINE_NONE;
1396 if (list_empty(&ci->i_cap_snaps)) 1396 if (!(flags & CEPH_CLIENT_CAPS_PENDING_CAPSNAP) &&
1397 arg.flags = CEPH_CLIENT_CAPS_NO_CAPSNAP; 1397 !list_empty(&ci->i_cap_snaps)) {
1398 else 1398 struct ceph_cap_snap *capsnap;
1399 arg.flags = CEPH_CLIENT_CAPS_PENDING_CAPSNAP; 1399 list_for_each_entry_reverse(capsnap, &ci->i_cap_snaps, ci_item) {
1400 if (sync) 1400 if (capsnap->cap_flush.tid)
1401 arg.flags |= CEPH_CLIENT_CAPS_SYNC; 1401 break;
1402 if (capsnap->need_flush) {
1403 flags |= CEPH_CLIENT_CAPS_PENDING_CAPSNAP;
1404 break;
1405 }
1406 }
1407 }
1408 arg.flags = flags;
1402 1409
1403 spin_unlock(&ci->i_ceph_lock); 1410 spin_unlock(&ci->i_ceph_lock);
1404 1411
@@ -2085,7 +2092,7 @@ ack:
2085 sent++; 2092 sent++;
2086 2093
2087 /* __send_cap drops i_ceph_lock */ 2094 /* __send_cap drops i_ceph_lock */
2088 delayed += __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, false, 2095 delayed += __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, 0,
2089 cap_used, want, retain, flushing, 2096 cap_used, want, retain, flushing,
2090 flush_tid, oldest_flush_tid); 2097 flush_tid, oldest_flush_tid);
2091 goto retry; /* retake i_ceph_lock and restart our cap scan. */ 2098 goto retry; /* retake i_ceph_lock and restart our cap scan. */
@@ -2155,7 +2162,8 @@ retry_locked:
2155 &flush_tid, &oldest_flush_tid); 2162 &flush_tid, &oldest_flush_tid);
2156 2163
2157 /* __send_cap drops i_ceph_lock */ 2164 /* __send_cap drops i_ceph_lock */
2158 delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH, true, 2165 delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH,
2166 CEPH_CLIENT_CAPS_SYNC,
2159 __ceph_caps_used(ci), 2167 __ceph_caps_used(ci),
2160 __ceph_caps_wanted(ci), 2168 __ceph_caps_wanted(ci),
2161 (cap->issued | cap->implemented), 2169 (cap->issued | cap->implemented),
@@ -2328,9 +2336,17 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
2328 struct ceph_cap_flush *cf; 2336 struct ceph_cap_flush *cf;
2329 int ret; 2337 int ret;
2330 u64 first_tid = 0; 2338 u64 first_tid = 0;
2339 u64 last_snap_flush = 0;
2331 2340
2332 ci->i_ceph_flags &= ~CEPH_I_KICK_FLUSH; 2341 ci->i_ceph_flags &= ~CEPH_I_KICK_FLUSH;
2333 2342
2343 list_for_each_entry_reverse(cf, &ci->i_cap_flush_list, i_list) {
2344 if (!cf->caps) {
2345 last_snap_flush = cf->tid;
2346 break;
2347 }
2348 }
2349
2334 list_for_each_entry(cf, &ci->i_cap_flush_list, i_list) { 2350 list_for_each_entry(cf, &ci->i_cap_flush_list, i_list) {
2335 if (cf->tid < first_tid) 2351 if (cf->tid < first_tid)
2336 continue; 2352 continue;
@@ -2348,10 +2364,13 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
2348 dout("kick_flushing_caps %p cap %p tid %llu %s\n", 2364 dout("kick_flushing_caps %p cap %p tid %llu %s\n",
2349 inode, cap, cf->tid, ceph_cap_string(cf->caps)); 2365 inode, cap, cf->tid, ceph_cap_string(cf->caps));
2350 ci->i_ceph_flags |= CEPH_I_NODELAY; 2366 ci->i_ceph_flags |= CEPH_I_NODELAY;
2367
2351 ret = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH, 2368 ret = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH,
2352 false, __ceph_caps_used(ci), 2369 (cf->tid < last_snap_flush ?
2370 CEPH_CLIENT_CAPS_PENDING_CAPSNAP : 0),
2371 __ceph_caps_used(ci),
2353 __ceph_caps_wanted(ci), 2372 __ceph_caps_wanted(ci),
2354 cap->issued | cap->implemented, 2373 (cap->issued | cap->implemented),
2355 cf->caps, cf->tid, oldest_flush_tid); 2374 cf->caps, cf->tid, oldest_flush_tid);
2356 if (ret) { 2375 if (ret) {
2357 pr_err("kick_flushing_caps: error sending " 2376 pr_err("kick_flushing_caps: error sending "