summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2015-06-10 05:26:13 -0400
committerIlya Dryomov <idryomov@gmail.com>2015-06-25 04:49:31 -0400
commitf66fd9f0952187d274c13c136b74548f792c1925 (patch)
treec021f04f69b116f2673fdfb2354a99871f8f03a4 /fs/ceph/caps.c
parente548e9b93d3e565e42b938a99804114565be1f81 (diff)
ceph: pre-allocate data structure that tracks caps flushing
Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 69a16044ec41..dd7b20adf1d4 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1356,7 +1356,8 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci)
1356 * Caller is then responsible for calling __mark_inode_dirty with the 1356 * Caller is then responsible for calling __mark_inode_dirty with the
1357 * returned flags value. 1357 * returned flags value.
1358 */ 1358 */
1359int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) 1359int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
1360 struct ceph_cap_flush **pcf)
1360{ 1361{
1361 struct ceph_mds_client *mdsc = 1362 struct ceph_mds_client *mdsc =
1362 ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; 1363 ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
@@ -1376,6 +1377,9 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
1376 ceph_cap_string(was | mask)); 1377 ceph_cap_string(was | mask));
1377 ci->i_dirty_caps |= mask; 1378 ci->i_dirty_caps |= mask;
1378 if (was == 0) { 1379 if (was == 0) {
1380 WARN_ON_ONCE(ci->i_prealloc_cap_flush);
1381 swap(ci->i_prealloc_cap_flush, *pcf);
1382
1379 if (!ci->i_head_snapc) { 1383 if (!ci->i_head_snapc) {
1380 WARN_ON_ONCE(!rwsem_is_locked(&mdsc->snap_rwsem)); 1384 WARN_ON_ONCE(!rwsem_is_locked(&mdsc->snap_rwsem));
1381 ci->i_head_snapc = ceph_get_snap_context( 1385 ci->i_head_snapc = ceph_get_snap_context(
@@ -1391,6 +1395,8 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
1391 ihold(inode); 1395 ihold(inode);
1392 dirty |= I_DIRTY_SYNC; 1396 dirty |= I_DIRTY_SYNC;
1393 } 1397 }
1398 } else {
1399 WARN_ON_ONCE(!ci->i_prealloc_cap_flush);
1394 } 1400 }
1395 BUG_ON(list_empty(&ci->i_dirty_item)); 1401 BUG_ON(list_empty(&ci->i_dirty_item));
1396 if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && 1402 if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) &&
@@ -1446,6 +1452,17 @@ static void __add_cap_flushing_to_mdsc(struct ceph_mds_client *mdsc,
1446 rb_insert_color(&cf->g_node, &mdsc->cap_flush_tree); 1452 rb_insert_color(&cf->g_node, &mdsc->cap_flush_tree);
1447} 1453}
1448 1454
1455struct ceph_cap_flush *ceph_alloc_cap_flush(void)
1456{
1457 return kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL);
1458}
1459
1460void ceph_free_cap_flush(struct ceph_cap_flush *cf)
1461{
1462 if (cf)
1463 kmem_cache_free(ceph_cap_flush_cachep, cf);
1464}
1465
1449static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc) 1466static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc)
1450{ 1467{
1451 struct rb_node *n = rb_first(&mdsc->cap_flush_tree); 1468 struct rb_node *n = rb_first(&mdsc->cap_flush_tree);
@@ -1469,11 +1486,12 @@ static int __mark_caps_flushing(struct inode *inode,
1469{ 1486{
1470 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; 1487 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
1471 struct ceph_inode_info *ci = ceph_inode(inode); 1488 struct ceph_inode_info *ci = ceph_inode(inode);
1472 struct ceph_cap_flush *cf; 1489 struct ceph_cap_flush *cf = NULL;
1473 int flushing; 1490 int flushing;
1474 1491
1475 BUG_ON(ci->i_dirty_caps == 0); 1492 BUG_ON(ci->i_dirty_caps == 0);
1476 BUG_ON(list_empty(&ci->i_dirty_item)); 1493 BUG_ON(list_empty(&ci->i_dirty_item));
1494 BUG_ON(!ci->i_prealloc_cap_flush);
1477 1495
1478 flushing = ci->i_dirty_caps; 1496 flushing = ci->i_dirty_caps;
1479 dout("__mark_caps_flushing flushing %s, flushing_caps %s -> %s\n", 1497 dout("__mark_caps_flushing flushing %s, flushing_caps %s -> %s\n",
@@ -1484,7 +1502,7 @@ static int __mark_caps_flushing(struct inode *inode,
1484 ci->i_dirty_caps = 0; 1502 ci->i_dirty_caps = 0;
1485 dout(" inode %p now !dirty\n", inode); 1503 dout(" inode %p now !dirty\n", inode);
1486 1504
1487 cf = kmalloc(sizeof(*cf), GFP_ATOMIC); 1505 swap(cf, ci->i_prealloc_cap_flush);
1488 cf->caps = flushing; 1506 cf->caps = flushing;
1489 cf->kick = false; 1507 cf->kick = false;
1490 1508
@@ -3075,7 +3093,7 @@ out:
3075 cf = list_first_entry(&to_remove, 3093 cf = list_first_entry(&to_remove,
3076 struct ceph_cap_flush, list); 3094 struct ceph_cap_flush, list);
3077 list_del(&cf->list); 3095 list_del(&cf->list);
3078 kfree(cf); 3096 ceph_free_cap_flush(cf);
3079 } 3097 }
3080 if (drop) 3098 if (drop)
3081 iput(inode); 3099 iput(inode);