aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-08-16 16:37:31 -0400
committerSage Weil <sage@newdream.net>2010-08-22 18:16:47 -0400
commited326044489ed89c740c50a3df5dffc9c3b20b96 (patch)
tree364fb2896488cd2c7964960e01fa123d2b6ecb51 /fs/ceph
parent4a625be47243e0e07dedd0a1a6b94c66c2ab93ba (diff)
ceph: queue cap snap writeback for realm children on snap update
When a realm is updated, we need to queue writeback on inodes in that realm _and_ its children. Otherwise, if the inode gets cowed on the server, we can get a hang later due to out-of-sync cap/snap state. Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/snap.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 2cb190c2bd99..6bdbf3ae7082 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -548,6 +548,41 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
548 return 1; /* caller may want to ceph_flush_snaps */ 548 return 1; /* caller may want to ceph_flush_snaps */
549} 549}
550 550
551/*
552 * Queue cap_snaps for snap writeback for this realm and its children.
553 * Called under snap_rwsem, so realm topology won't change.
554 */
555static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
556{
557 struct ceph_inode_info *ci;
558 struct inode *lastinode = NULL;
559 struct ceph_snap_realm *child;
560
561 dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);
562
563 spin_lock(&realm->inodes_with_caps_lock);
564 list_for_each_entry(ci, &realm->inodes_with_caps,
565 i_snap_realm_item) {
566 struct inode *inode = igrab(&ci->vfs_inode);
567 if (!inode)
568 continue;
569 spin_unlock(&realm->inodes_with_caps_lock);
570 if (lastinode)
571 iput(lastinode);
572 lastinode = inode;
573 ceph_queue_cap_snap(ci);
574 spin_lock(&realm->inodes_with_caps_lock);
575 }
576 spin_unlock(&realm->inodes_with_caps_lock);
577 if (lastinode)
578 iput(lastinode);
579
580 dout("queue_realm_cap_snaps %p %llx children\n", realm, realm->ino);
581 list_for_each_entry(child, &realm->children, child_item)
582 queue_realm_cap_snaps(child);
583
584 dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
585}
551 586
552/* 587/*
553 * Parse and apply a snapblob "snap trace" from the MDS. This specifies 588 * Parse and apply a snapblob "snap trace" from the MDS. This specifies
@@ -598,29 +633,8 @@ more:
598 * 633 *
599 * ...unless it's a snap deletion! 634 * ...unless it's a snap deletion!
600 */ 635 */
601 if (!deletion) { 636 if (!deletion)
602 struct ceph_inode_info *ci; 637 queue_realm_cap_snaps(realm);
603 struct inode *lastinode = NULL;
604
605 spin_lock(&realm->inodes_with_caps_lock);
606 list_for_each_entry(ci, &realm->inodes_with_caps,
607 i_snap_realm_item) {
608 struct inode *inode = igrab(&ci->vfs_inode);
609 if (!inode)
610 continue;
611 spin_unlock(&realm->inodes_with_caps_lock);
612 if (lastinode)
613 iput(lastinode);
614 lastinode = inode;
615 ceph_queue_cap_snap(ci);
616 spin_lock(&realm->inodes_with_caps_lock);
617 }
618 spin_unlock(&realm->inodes_with_caps_lock);
619 if (lastinode)
620 iput(lastinode);
621 dout("update_snap_trace cap_snaps queued\n");
622 }
623
624 } else { 638 } else {
625 dout("update_snap_trace %llx %p seq %lld unchanged\n", 639 dout("update_snap_trace %llx %p seq %lld unchanged\n",
626 realm->ino, realm, realm->seq); 640 realm->ino, realm, realm->seq);