summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2015-06-09 05:20:12 -0400
committerIlya Dryomov <idryomov@gmail.com>2015-06-25 04:49:31 -0400
commit8310b08913eca8aee98744c9aff1ec0d1f603b19 (patch)
treeac58f8ea0c44c98a675242c1a2a338f6333f03ba /fs/ceph/caps.c
parent553adfd941f8ca622965ef809553d918ea039929 (diff)
ceph: track pending caps flushing globally
So we know TID of the oldest pending caps flushing. Later patch will send this information to MDS, so that MDS can trim its completed caps flush list. Tracking pending caps flushing globally also simplifies syncfs code. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 9a25f8d66fbc..0295048724d2 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1415,6 +1415,29 @@ static void __add_cap_flushing_to_inode(struct ceph_inode_info *ci,
1415 rb_insert_color(&cf->i_node, &ci->i_cap_flush_tree); 1415 rb_insert_color(&cf->i_node, &ci->i_cap_flush_tree);
1416} 1416}
1417 1417
1418static void __add_cap_flushing_to_mdsc(struct ceph_mds_client *mdsc,
1419 struct ceph_cap_flush *cf)
1420{
1421 struct rb_node **p = &mdsc->cap_flush_tree.rb_node;
1422 struct rb_node *parent = NULL;
1423 struct ceph_cap_flush *other = NULL;
1424
1425 while (*p) {
1426 parent = *p;
1427 other = rb_entry(parent, struct ceph_cap_flush, g_node);
1428
1429 if (cf->tid < other->tid)
1430 p = &(*p)->rb_left;
1431 else if (cf->tid > other->tid)
1432 p = &(*p)->rb_right;
1433 else
1434 BUG();
1435 }
1436
1437 rb_link_node(&cf->g_node, parent, p);
1438 rb_insert_color(&cf->g_node, &mdsc->cap_flush_tree);
1439}
1440
1418/* 1441/*
1419 * Add dirty inode to the flushing list. Assigned a seq number so we 1442 * Add dirty inode to the flushing list. Assigned a seq number so we
1420 * can wait for caps to flush without starving. 1443 * can wait for caps to flush without starving.
@@ -1449,17 +1472,16 @@ static int __mark_caps_flushing(struct inode *inode,
1449 list_del_init(&ci->i_dirty_item); 1472 list_del_init(&ci->i_dirty_item);
1450 1473
1451 cf->tid = ++mdsc->last_cap_flush_tid; 1474 cf->tid = ++mdsc->last_cap_flush_tid;
1475 __add_cap_flushing_to_mdsc(mdsc, cf);
1452 1476
1453 if (list_empty(&ci->i_flushing_item)) { 1477 if (list_empty(&ci->i_flushing_item)) {
1454 ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
1455 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing); 1478 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing);
1456 mdsc->num_cap_flushing++; 1479 mdsc->num_cap_flushing++;
1457 dout(" inode %p now flushing seq %lld\n", inode, 1480 dout(" inode %p now flushing tid %llu\n", inode, cf->tid);
1458 ci->i_cap_flush_seq);
1459 } else { 1481 } else {
1460 list_move_tail(&ci->i_flushing_item, &session->s_cap_flushing); 1482 list_move_tail(&ci->i_flushing_item, &session->s_cap_flushing);
1461 dout(" inode %p now flushing (more) seq %lld\n", inode, 1483 dout(" inode %p now flushing (more) tid %llu\n",
1462 ci->i_cap_flush_seq); 1484 inode, cf->tid);
1463 } 1485 }
1464 spin_unlock(&mdsc->cap_dirty_lock); 1486 spin_unlock(&mdsc->cap_dirty_lock);
1465 1487
@@ -2123,8 +2145,8 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc,
2123 2145
2124 spin_lock(&ci->i_ceph_lock); 2146 spin_lock(&ci->i_ceph_lock);
2125 cap = ci->i_auth_cap; 2147 cap = ci->i_auth_cap;
2126 dout("kick_flushing_inode_caps %p flushing %s flush_seq %lld\n", inode, 2148 dout("kick_flushing_inode_caps %p flushing %s\n", inode,
2127 ceph_cap_string(ci->i_flushing_caps), ci->i_cap_flush_seq); 2149 ceph_cap_string(ci->i_flushing_caps));
2128 2150
2129 __ceph_flush_snaps(ci, &session, 1); 2151 __ceph_flush_snaps(ci, &session, 1);
2130 2152
@@ -2921,12 +2943,23 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
2921 ceph_cap_string(cleaned), ceph_cap_string(ci->i_flushing_caps), 2943 ceph_cap_string(cleaned), ceph_cap_string(ci->i_flushing_caps),
2922 ceph_cap_string(ci->i_flushing_caps & ~cleaned)); 2944 ceph_cap_string(ci->i_flushing_caps & ~cleaned));
2923 2945
2924 if (ci->i_flushing_caps == (ci->i_flushing_caps & ~cleaned)) 2946 if (list_empty(&to_remove) && !cleaned)
2925 goto out; 2947 goto out;
2926 2948
2927 ci->i_flushing_caps &= ~cleaned; 2949 ci->i_flushing_caps &= ~cleaned;
2928 2950
2929 spin_lock(&mdsc->cap_dirty_lock); 2951 spin_lock(&mdsc->cap_dirty_lock);
2952
2953 if (!list_empty(&to_remove)) {
2954 list_for_each_entry(cf, &to_remove, list)
2955 rb_erase(&cf->g_node, &mdsc->cap_flush_tree);
2956
2957 n = rb_first(&mdsc->cap_flush_tree);
2958 cf = n ? rb_entry(n, struct ceph_cap_flush, g_node) : NULL;
2959 if (!cf || cf->tid > flush_tid)
2960 wake_up_all(&mdsc->cap_flushing_wq);
2961 }
2962
2930 if (ci->i_flushing_caps == 0) { 2963 if (ci->i_flushing_caps == 0) {
2931 list_del_init(&ci->i_flushing_item); 2964 list_del_init(&ci->i_flushing_item);
2932 if (!list_empty(&session->s_cap_flushing)) 2965 if (!list_empty(&session->s_cap_flushing))
@@ -2936,7 +2969,6 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
2936 struct ceph_inode_info, 2969 struct ceph_inode_info,
2937 i_flushing_item)->vfs_inode); 2970 i_flushing_item)->vfs_inode);
2938 mdsc->num_cap_flushing--; 2971 mdsc->num_cap_flushing--;
2939 wake_up_all(&mdsc->cap_flushing_wq);
2940 dout(" inode %p now !flushing\n", inode); 2972 dout(" inode %p now !flushing\n", inode);
2941 2973
2942 if (ci->i_dirty_caps == 0) { 2974 if (ci->i_dirty_caps == 0) {