diff options
author | Sage Weil <sage@newdream.net> | 2010-08-16 16:37:31 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-08-22 18:16:47 -0400 |
commit | ed326044489ed89c740c50a3df5dffc9c3b20b96 (patch) | |
tree | 364fb2896488cd2c7964960e01fa123d2b6ecb51 /fs/ceph | |
parent | 4a625be47243e0e07dedd0a1a6b94c66c2ab93ba (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.c | 60 |
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 | */ | ||
555 | static 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); |