summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-07-05 23:12:56 -0400
committerIlya Dryomov <idryomov@gmail.com>2016-07-27 21:00:42 -0400
commite4500b5e35c213e0f97be7cb69328c0877203a79 (patch)
tree67ce2673600daf716923ac9b8675796bbd5127b1 /fs/ceph/caps.c
parent3609404f8c782c01fe626a03949641dddbc65c34 (diff)
ceph: use list instead of rbtree to track cap flushes
We don't have requirement of searching cap flush by TID. In most cases, we just need to know TID of the oldest cap flush. List is ideal for this usage. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c120
1 files changed, 31 insertions, 89 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 698cf002d3f1..e0efa75a1b98 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1413,52 +1413,6 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
1413 return dirty; 1413 return dirty;
1414} 1414}
1415 1415
1416static void __add_cap_flushing_to_inode(struct ceph_inode_info *ci,
1417 struct ceph_cap_flush *cf)
1418{
1419 struct rb_node **p = &ci->i_cap_flush_tree.rb_node;
1420 struct rb_node *parent = NULL;
1421 struct ceph_cap_flush *other = NULL;
1422
1423 while (*p) {
1424 parent = *p;
1425 other = rb_entry(parent, struct ceph_cap_flush, i_node);
1426
1427 if (cf->tid < other->tid)
1428 p = &(*p)->rb_left;
1429 else if (cf->tid > other->tid)
1430 p = &(*p)->rb_right;
1431 else
1432 BUG();
1433 }
1434
1435 rb_link_node(&cf->i_node, parent, p);
1436 rb_insert_color(&cf->i_node, &ci->i_cap_flush_tree);
1437}
1438
1439static void __add_cap_flushing_to_mdsc(struct ceph_mds_client *mdsc,
1440 struct ceph_cap_flush *cf)
1441{
1442 struct rb_node **p = &mdsc->cap_flush_tree.rb_node;
1443 struct rb_node *parent = NULL;
1444 struct ceph_cap_flush *other = NULL;
1445
1446 while (*p) {
1447 parent = *p;
1448 other = rb_entry(parent, struct ceph_cap_flush, g_node);
1449
1450 if (cf->tid < other->tid)
1451 p = &(*p)->rb_left;
1452 else if (cf->tid > other->tid)
1453 p = &(*p)->rb_right;
1454 else
1455 BUG();
1456 }
1457
1458 rb_link_node(&cf->g_node, parent, p);
1459 rb_insert_color(&cf->g_node, &mdsc->cap_flush_tree);
1460}
1461
1462struct ceph_cap_flush *ceph_alloc_cap_flush(void) 1416struct ceph_cap_flush *ceph_alloc_cap_flush(void)
1463{ 1417{
1464 return kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL); 1418 return kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL);
@@ -1472,10 +1426,10 @@ void ceph_free_cap_flush(struct ceph_cap_flush *cf)
1472 1426
1473static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc) 1427static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc)
1474{ 1428{
1475 struct rb_node *n = rb_first(&mdsc->cap_flush_tree); 1429 if (!list_empty(&mdsc->cap_flush_list)) {
1476 if (n) {
1477 struct ceph_cap_flush *cf = 1430 struct ceph_cap_flush *cf =
1478 rb_entry(n, struct ceph_cap_flush, g_node); 1431 list_first_entry(&mdsc->cap_flush_list,
1432 struct ceph_cap_flush, g_list);
1479 return cf->tid; 1433 return cf->tid;
1480 } 1434 }
1481 return 0; 1435 return 0;
@@ -1516,7 +1470,7 @@ static int __mark_caps_flushing(struct inode *inode,
1516 list_del_init(&ci->i_dirty_item); 1470 list_del_init(&ci->i_dirty_item);
1517 1471
1518 cf->tid = ++mdsc->last_cap_flush_tid; 1472 cf->tid = ++mdsc->last_cap_flush_tid;
1519 __add_cap_flushing_to_mdsc(mdsc, cf); 1473 list_add_tail(&cf->g_list, &mdsc->cap_flush_list);
1520 *oldest_flush_tid = __get_oldest_flush_tid(mdsc); 1474 *oldest_flush_tid = __get_oldest_flush_tid(mdsc);
1521 1475
1522 if (list_empty(&ci->i_flushing_item)) { 1476 if (list_empty(&ci->i_flushing_item)) {
@@ -1530,7 +1484,7 @@ static int __mark_caps_flushing(struct inode *inode,
1530 } 1484 }
1531 spin_unlock(&mdsc->cap_dirty_lock); 1485 spin_unlock(&mdsc->cap_dirty_lock);
1532 1486
1533 __add_cap_flushing_to_inode(ci, cf); 1487 list_add_tail(&cf->i_list, &ci->i_cap_flush_list);
1534 1488
1535 *flush_tid = cf->tid; 1489 *flush_tid = cf->tid;
1536 return flushing; 1490 return flushing;
@@ -1890,10 +1844,10 @@ retry:
1890 spin_unlock(&ci->i_ceph_lock); 1844 spin_unlock(&ci->i_ceph_lock);
1891 } 1845 }
1892 } else { 1846 } else {
1893 struct rb_node *n = rb_last(&ci->i_cap_flush_tree); 1847 if (!list_empty(&ci->i_cap_flush_list)) {
1894 if (n) {
1895 struct ceph_cap_flush *cf = 1848 struct ceph_cap_flush *cf =
1896 rb_entry(n, struct ceph_cap_flush, i_node); 1849 list_last_entry(&ci->i_cap_flush_list,
1850 struct ceph_cap_flush, i_list);
1897 flush_tid = cf->tid; 1851 flush_tid = cf->tid;
1898 } 1852 }
1899 flushing = ci->i_flushing_caps; 1853 flushing = ci->i_flushing_caps;
@@ -1913,14 +1867,13 @@ out:
1913static int caps_are_flushed(struct inode *inode, u64 flush_tid) 1867static int caps_are_flushed(struct inode *inode, u64 flush_tid)
1914{ 1868{
1915 struct ceph_inode_info *ci = ceph_inode(inode); 1869 struct ceph_inode_info *ci = ceph_inode(inode);
1916 struct ceph_cap_flush *cf;
1917 struct rb_node *n;
1918 int ret = 1; 1870 int ret = 1;
1919 1871
1920 spin_lock(&ci->i_ceph_lock); 1872 spin_lock(&ci->i_ceph_lock);
1921 n = rb_first(&ci->i_cap_flush_tree); 1873 if (!list_empty(&ci->i_cap_flush_list)) {
1922 if (n) { 1874 struct ceph_cap_flush * cf =
1923 cf = rb_entry(n, struct ceph_cap_flush, i_node); 1875 list_first_entry(&ci->i_cap_flush_list,
1876 struct ceph_cap_flush, i_list);
1924 if (cf->tid <= flush_tid) 1877 if (cf->tid <= flush_tid)
1925 ret = 0; 1878 ret = 0;
1926 } 1879 }
@@ -2083,7 +2036,6 @@ static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
2083 struct inode *inode = &ci->vfs_inode; 2036 struct inode *inode = &ci->vfs_inode;
2084 struct ceph_cap *cap; 2037 struct ceph_cap *cap;
2085 struct ceph_cap_flush *cf; 2038 struct ceph_cap_flush *cf;
2086 struct rb_node *n;
2087 int delayed = 0; 2039 int delayed = 0;
2088 u64 first_tid = 0; 2040 u64 first_tid = 0;
2089 u64 oldest_flush_tid; 2041 u64 oldest_flush_tid;
@@ -2092,8 +2044,11 @@ static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
2092 oldest_flush_tid = __get_oldest_flush_tid(mdsc); 2044 oldest_flush_tid = __get_oldest_flush_tid(mdsc);
2093 spin_unlock(&mdsc->cap_dirty_lock); 2045 spin_unlock(&mdsc->cap_dirty_lock);
2094 2046
2095 while (true) { 2047 spin_lock(&ci->i_ceph_lock);
2096 spin_lock(&ci->i_ceph_lock); 2048 list_for_each_entry(cf, &ci->i_cap_flush_list, i_list) {
2049 if (cf->tid < first_tid)
2050 continue;
2051
2097 cap = ci->i_auth_cap; 2052 cap = ci->i_auth_cap;
2098 if (!(cap && cap->session == session)) { 2053 if (!(cap && cap->session == session)) {
2099 pr_err("%p auth cap %p not mds%d ???\n", inode, 2054 pr_err("%p auth cap %p not mds%d ???\n", inode,
@@ -2102,18 +2057,6 @@ static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
2102 break; 2057 break;
2103 } 2058 }
2104 2059
2105 for (n = rb_first(&ci->i_cap_flush_tree); n; n = rb_next(n)) {
2106 cf = rb_entry(n, struct ceph_cap_flush, i_node);
2107 if (cf->tid >= first_tid)
2108 break;
2109 }
2110 if (!n) {
2111 spin_unlock(&ci->i_ceph_lock);
2112 break;
2113 }
2114
2115 cf = rb_entry(n, struct ceph_cap_flush, i_node);
2116
2117 first_tid = cf->tid + 1; 2060 first_tid = cf->tid + 1;
2118 2061
2119 dout("kick_flushing_caps %p cap %p tid %llu %s\n", inode, 2062 dout("kick_flushing_caps %p cap %p tid %llu %s\n", inode,
@@ -2123,7 +2066,10 @@ static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
2123 __ceph_caps_wanted(ci), 2066 __ceph_caps_wanted(ci),
2124 cap->issued | cap->implemented, 2067 cap->issued | cap->implemented,
2125 cf->caps, cf->tid, oldest_flush_tid); 2068 cf->caps, cf->tid, oldest_flush_tid);
2069
2070 spin_lock(&ci->i_ceph_lock);
2126 } 2071 }
2072 spin_unlock(&ci->i_ceph_lock);
2127 return delayed; 2073 return delayed;
2128} 2074}
2129 2075
@@ -2995,23 +2941,19 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
2995{ 2941{
2996 struct ceph_inode_info *ci = ceph_inode(inode); 2942 struct ceph_inode_info *ci = ceph_inode(inode);
2997 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; 2943 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
2998 struct ceph_cap_flush *cf; 2944 struct ceph_cap_flush *cf, *tmp_cf;
2999 struct rb_node *n;
3000 LIST_HEAD(to_remove); 2945 LIST_HEAD(to_remove);
3001 unsigned seq = le32_to_cpu(m->seq); 2946 unsigned seq = le32_to_cpu(m->seq);
3002 int dirty = le32_to_cpu(m->dirty); 2947 int dirty = le32_to_cpu(m->dirty);
3003 int cleaned = 0; 2948 int cleaned = 0;
3004 int drop = 0; 2949 int drop = 0;
3005 2950
3006 n = rb_first(&ci->i_cap_flush_tree); 2951 list_for_each_entry_safe(cf, tmp_cf, &ci->i_cap_flush_list, i_list) {
3007 while (n) {
3008 cf = rb_entry(n, struct ceph_cap_flush, i_node);
3009 n = rb_next(&cf->i_node);
3010 if (cf->tid == flush_tid) 2952 if (cf->tid == flush_tid)
3011 cleaned = cf->caps; 2953 cleaned = cf->caps;
3012 if (cf->tid <= flush_tid) { 2954 if (cf->tid <= flush_tid) {
3013 rb_erase(&cf->i_node, &ci->i_cap_flush_tree); 2955 list_del(&cf->i_list);
3014 list_add_tail(&cf->list, &to_remove); 2956 list_add_tail(&cf->i_list, &to_remove);
3015 } else { 2957 } else {
3016 cleaned &= ~cf->caps; 2958 cleaned &= ~cf->caps;
3017 if (!cleaned) 2959 if (!cleaned)
@@ -3033,12 +2975,12 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
3033 spin_lock(&mdsc->cap_dirty_lock); 2975 spin_lock(&mdsc->cap_dirty_lock);
3034 2976
3035 if (!list_empty(&to_remove)) { 2977 if (!list_empty(&to_remove)) {
3036 list_for_each_entry(cf, &to_remove, list) 2978 u64 oldest_flush_tid;
3037 rb_erase(&cf->g_node, &mdsc->cap_flush_tree); 2979 list_for_each_entry(cf, &to_remove, i_list)
2980 list_del(&cf->g_list);
3038 2981
3039 n = rb_first(&mdsc->cap_flush_tree); 2982 oldest_flush_tid = __get_oldest_flush_tid(mdsc);
3040 cf = n ? rb_entry(n, struct ceph_cap_flush, g_node) : NULL; 2983 if (oldest_flush_tid == 0 || oldest_flush_tid > flush_tid)
3041 if (!cf || cf->tid > flush_tid)
3042 wake_up_all(&mdsc->cap_flushing_wq); 2984 wake_up_all(&mdsc->cap_flushing_wq);
3043 } 2985 }
3044 2986
@@ -3075,8 +3017,8 @@ out:
3075 3017
3076 while (!list_empty(&to_remove)) { 3018 while (!list_empty(&to_remove)) {
3077 cf = list_first_entry(&to_remove, 3019 cf = list_first_entry(&to_remove,
3078 struct ceph_cap_flush, list); 3020 struct ceph_cap_flush, i_list);
3079 list_del(&cf->list); 3021 list_del(&cf->i_list);
3080 ceph_free_cap_flush(cf); 3022 ceph_free_cap_flush(cf);
3081 } 3023 }
3082 if (drop) 3024 if (drop)