aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-10-14 17:27:38 -0400
committerSage Weil <sage@newdream.net>2009-10-15 21:14:35 -0400
commitafcdaea3f2a78ce4873bd7e98a6d603bda23d167 (patch)
tree08defc298e2c27816d70bd41c8c3ecc80a82ba79 /fs/ceph/caps.c
parentcdc35f96277314bbfeefd0505410cabd69aebd8d (diff)
ceph: flush dirty caps via the cap_dirty list
Previously we were flushing dirty caps by passing an extra flag when traversing the delayed caps list. Besides being a bit ugly, that can also miss caps that are dirty but didn't result in a cap requeue: notably, mark_caps_dirty(). Separate the flushing into a separate helper, and traverse the cap_dirty list. This also brings i_dirty_item in line with i_dirty_caps: we are on the list IFF caps != 0. We carry an inode ref IFF dirty_caps|flushing_caps != 0. Lose the unused return value from __ceph_mark_caps_dirty(). Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c76
1 files changed, 53 insertions, 23 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 111439d883d2..40b8d3471244 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -997,7 +997,7 @@ void ceph_queue_caps_release(struct inode *inode)
997 if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) { 997 if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
998 dout(" release msg %p full\n", msg); 998 dout(" release msg %p full\n", msg);
999 list_move_tail(&msg->list_head, 999 list_move_tail(&msg->list_head,
1000 &session->s_cap_releases_done); 1000 &session->s_cap_releases_done);
1001 } else { 1001 } else {
1002 dout(" release msg %p at %d/%d (%d)\n", msg, 1002 dout(" release msg %p at %d/%d (%d)\n", msg,
1003 (int)le32_to_cpu(head->num), 1003 (int)le32_to_cpu(head->num),
@@ -1292,14 +1292,20 @@ static int __mark_caps_flushing(struct inode *inode,
1292 ceph_cap_string(ci->i_flushing_caps | flushing)); 1292 ceph_cap_string(ci->i_flushing_caps | flushing));
1293 ci->i_flushing_caps |= flushing; 1293 ci->i_flushing_caps |= flushing;
1294 ci->i_dirty_caps = 0; 1294 ci->i_dirty_caps = 0;
1295 dout(" inode %p now !dirty\n", inode);
1295 1296
1296 spin_lock(&mdsc->cap_dirty_lock); 1297 spin_lock(&mdsc->cap_dirty_lock);
1298 list_del_init(&ci->i_dirty_item);
1299
1300 ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
1297 if (list_empty(&ci->i_flushing_item)) { 1301 if (list_empty(&ci->i_flushing_item)) {
1298 list_del_init(&ci->i_dirty_item);
1299 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing); 1302 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing);
1300 mdsc->num_cap_flushing++; 1303 mdsc->num_cap_flushing++;
1301 ci->i_cap_flush_seq = ++mdsc->cap_flush_seq; 1304 dout(" inode %p now flushing seq %lld\n", inode,
1302 dout(" inode %p now flushing seq %lld\n", &ci->vfs_inode, 1305 ci->i_cap_flush_seq);
1306 } else {
1307 list_move_tail(&ci->i_flushing_item, &session->s_cap_flushing);
1308 dout(" inode %p now flushing (more) seq %lld\n", inode,
1303 ci->i_cap_flush_seq); 1309 ci->i_cap_flush_seq);
1304 } 1310 }
1305 spin_unlock(&mdsc->cap_dirty_lock); 1311 spin_unlock(&mdsc->cap_dirty_lock);
@@ -1555,32 +1561,33 @@ ack:
1555 * Mark caps dirty. If inode is newly dirty, add to the global dirty 1561 * Mark caps dirty. If inode is newly dirty, add to the global dirty
1556 * list. 1562 * list.
1557 */ 1563 */
1558int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) 1564void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
1559{ 1565{
1560 struct ceph_mds_client *mdsc = &ceph_client(ci->vfs_inode.i_sb)->mdsc; 1566 struct ceph_mds_client *mdsc = &ceph_client(ci->vfs_inode.i_sb)->mdsc;
1561 struct inode *inode = &ci->vfs_inode; 1567 struct inode *inode = &ci->vfs_inode;
1562 int was = __ceph_caps_dirty(ci); 1568 int was_dirty = ci->i_dirty_caps;
1563 int dirty = 0; 1569 int dirty = 0;
1564 1570
1565 dout("__mark_dirty_caps %p %s dirty %s -> %s\n", &ci->vfs_inode, 1571 dout("__mark_dirty_caps %p %s dirty %s -> %s\n", &ci->vfs_inode,
1566 ceph_cap_string(mask), ceph_cap_string(ci->i_dirty_caps), 1572 ceph_cap_string(mask), ceph_cap_string(ci->i_dirty_caps),
1567 ceph_cap_string(ci->i_dirty_caps | mask)); 1573 ceph_cap_string(ci->i_dirty_caps | mask));
1568 ci->i_dirty_caps |= mask; 1574 ci->i_dirty_caps |= mask;
1569 if (!was) { 1575 if (!was_dirty) {
1570 dout(" inode %p now dirty\n", &ci->vfs_inode); 1576 dout(" inode %p now dirty\n", &ci->vfs_inode);
1571 spin_lock(&mdsc->cap_dirty_lock); 1577 spin_lock(&mdsc->cap_dirty_lock);
1572 list_add(&ci->i_dirty_item, &mdsc->cap_dirty); 1578 list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
1573 spin_unlock(&mdsc->cap_dirty_lock); 1579 spin_unlock(&mdsc->cap_dirty_lock);
1574 igrab(inode); 1580 if (ci->i_flushing_caps == 0) {
1575 dirty |= I_DIRTY_SYNC; 1581 igrab(inode);
1582 dirty |= I_DIRTY_SYNC;
1583 }
1576 } 1584 }
1577 if ((was & CEPH_CAP_FILE_BUFFER) && 1585 if (((was_dirty | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) &&
1578 (mask & CEPH_CAP_FILE_BUFFER)) 1586 (mask & CEPH_CAP_FILE_BUFFER))
1579 dirty |= I_DIRTY_DATASYNC; 1587 dirty |= I_DIRTY_DATASYNC;
1580 if (dirty) 1588 if (dirty)
1581 __mark_inode_dirty(inode, dirty); 1589 __mark_inode_dirty(inode, dirty);
1582 __cap_delay_requeue(mdsc, ci); 1590 __cap_delay_requeue(mdsc, ci);
1583 return was;
1584} 1591}
1585 1592
1586/* 1593/*
@@ -2327,7 +2334,7 @@ static void handle_cap_flush_ack(struct inode *inode,
2327 int dirty = le32_to_cpu(m->dirty); 2334 int dirty = le32_to_cpu(m->dirty);
2328 int cleaned = 0; 2335 int cleaned = 0;
2329 u64 flush_tid = le64_to_cpu(m->client_tid); 2336 u64 flush_tid = le64_to_cpu(m->client_tid);
2330 int old_dirty = 0, new_dirty = 0; 2337 int drop = 0;
2331 int i; 2338 int i;
2332 2339
2333 for (i = 0; i < CEPH_CAP_BITS; i++) 2340 for (i = 0; i < CEPH_CAP_BITS; i++)
@@ -2344,9 +2351,7 @@ static void handle_cap_flush_ack(struct inode *inode,
2344 if (ci->i_flushing_caps == (ci->i_flushing_caps & ~cleaned)) 2351 if (ci->i_flushing_caps == (ci->i_flushing_caps & ~cleaned))
2345 goto out; 2352 goto out;
2346 2353
2347 old_dirty = ci->i_dirty_caps | ci->i_flushing_caps;
2348 ci->i_flushing_caps &= ~cleaned; 2354 ci->i_flushing_caps &= ~cleaned;
2349 new_dirty = ci->i_dirty_caps | ci->i_flushing_caps;
2350 2355
2351 spin_lock(&mdsc->cap_dirty_lock); 2356 spin_lock(&mdsc->cap_dirty_lock);
2352 if (ci->i_flushing_caps == 0) { 2357 if (ci->i_flushing_caps == 0) {
@@ -2360,17 +2365,19 @@ static void handle_cap_flush_ack(struct inode *inode,
2360 mdsc->num_cap_flushing--; 2365 mdsc->num_cap_flushing--;
2361 wake_up(&mdsc->cap_flushing_wq); 2366 wake_up(&mdsc->cap_flushing_wq);
2362 dout(" inode %p now !flushing\n", inode); 2367 dout(" inode %p now !flushing\n", inode);
2363 } 2368
2364 if (old_dirty && !new_dirty) { 2369 if (ci->i_dirty_caps == 0) {
2365 dout(" inode %p now clean\n", inode); 2370 dout(" inode %p now clean\n", inode);
2366 list_del_init(&ci->i_dirty_item); 2371 BUG_ON(!list_empty(&ci->i_dirty_item));
2372 drop = 1;
2373 }
2367 } 2374 }
2368 spin_unlock(&mdsc->cap_dirty_lock); 2375 spin_unlock(&mdsc->cap_dirty_lock);
2369 wake_up(&ci->i_cap_wq); 2376 wake_up(&ci->i_cap_wq);
2370 2377
2371out: 2378out:
2372 spin_unlock(&inode->i_lock); 2379 spin_unlock(&inode->i_lock);
2373 if (old_dirty && !new_dirty) 2380 if (drop)
2374 iput(inode); 2381 iput(inode);
2375} 2382}
2376 2383
@@ -2676,14 +2683,11 @@ bad:
2676/* 2683/*
2677 * Delayed work handler to process end of delayed cap release LRU list. 2684 * Delayed work handler to process end of delayed cap release LRU list.
2678 */ 2685 */
2679void ceph_check_delayed_caps(struct ceph_mds_client *mdsc, int flushdirty) 2686void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
2680{ 2687{
2681 struct ceph_inode_info *ci; 2688 struct ceph_inode_info *ci;
2682 int flags = CHECK_CAPS_NODELAY; 2689 int flags = CHECK_CAPS_NODELAY;
2683 2690
2684 if (flushdirty)
2685 flags |= CHECK_CAPS_FLUSH;
2686
2687 dout("check_delayed_caps\n"); 2691 dout("check_delayed_caps\n");
2688 while (1) { 2692 while (1) {
2689 spin_lock(&mdsc->cap_delay_lock); 2693 spin_lock(&mdsc->cap_delay_lock);
@@ -2704,6 +2708,32 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc, int flushdirty)
2704} 2708}
2705 2709
2706/* 2710/*
2711 * Flush all dirty caps to the mds
2712 */
2713void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
2714{
2715 struct ceph_inode_info *ci;
2716 struct inode *inode;
2717
2718 dout("flush_dirty_caps\n");
2719 spin_lock(&mdsc->cap_dirty_lock);
2720 while (!list_empty(&mdsc->cap_dirty)) {
2721 ci = list_first_entry(&mdsc->cap_dirty,
2722 struct ceph_inode_info,
2723 i_dirty_item);
2724 inode = igrab(&ci->vfs_inode);
2725 spin_unlock(&mdsc->cap_dirty_lock);
2726 if (inode) {
2727 ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH,
2728 NULL);
2729 iput(inode);
2730 }
2731 spin_lock(&mdsc->cap_dirty_lock);
2732 }
2733 spin_unlock(&mdsc->cap_dirty_lock);
2734}
2735
2736/*
2707 * Drop open file reference. If we were the last open file, 2737 * Drop open file reference. If we were the last open file,
2708 * we may need to release capabilities to the MDS (or schedule 2738 * we may need to release capabilities to the MDS (or schedule
2709 * their delayed release). 2739 * their delayed release).