aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2017-08-28 04:36:53 -0400
committerIlya Dryomov <idryomov@gmail.com>2017-09-06 13:56:54 -0400
commit3ae0bebc49b3fb3c9fa9b62b95c5119a04aa7282 (patch)
treef98801c0cb9e80a22fee86c0001ec0a4e3153f0a
parentc8fd0d37f81dd38e3f319f4938b45a5aaf0dfc58 (diff)
ceph: queue cap snap only when snap realm's context changes
If we create capsnap when snap realm's context does not change, the new capsnap's snapc is equal to ci->i_head_snapc. Page writeback code can't differentiates dirty pages associated with the new capsnap from dirty pages associated with i_head_snapc. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r--fs/ceph/snap.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index dab5d6732345..1ffc8b426c1c 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -299,7 +299,8 @@ static int cmpu64_rev(const void *a, const void *b)
299/* 299/*
300 * build the snap context for a given realm. 300 * build the snap context for a given realm.
301 */ 301 */
302static int build_snap_context(struct ceph_snap_realm *realm) 302static int build_snap_context(struct ceph_snap_realm *realm,
303 struct list_head* dirty_realms)
303{ 304{
304 struct ceph_snap_realm *parent = realm->parent; 305 struct ceph_snap_realm *parent = realm->parent;
305 struct ceph_snap_context *snapc; 306 struct ceph_snap_context *snapc;
@@ -313,7 +314,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
313 */ 314 */
314 if (parent) { 315 if (parent) {
315 if (!parent->cached_context) { 316 if (!parent->cached_context) {
316 err = build_snap_context(parent); 317 err = build_snap_context(parent, dirty_realms);
317 if (err) 318 if (err)
318 goto fail; 319 goto fail;
319 } 320 }
@@ -332,7 +333,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
332 " (unchanged)\n", 333 " (unchanged)\n",
333 realm->ino, realm, realm->cached_context, 334 realm->ino, realm, realm->cached_context,
334 realm->cached_context->seq, 335 realm->cached_context->seq,
335 (unsigned int) realm->cached_context->num_snaps); 336 (unsigned int)realm->cached_context->num_snaps);
336 return 0; 337 return 0;
337 } 338 }
338 339
@@ -373,7 +374,11 @@ static int build_snap_context(struct ceph_snap_realm *realm)
373 realm->ino, realm, snapc, snapc->seq, 374 realm->ino, realm, snapc, snapc->seq,
374 (unsigned int) snapc->num_snaps); 375 (unsigned int) snapc->num_snaps);
375 376
376 ceph_put_snap_context(realm->cached_context); 377 if (realm->cached_context) {
378 ceph_put_snap_context(realm->cached_context);
379 /* queue realm for cap_snap creation */
380 list_add_tail(&realm->dirty_item, dirty_realms);
381 }
377 realm->cached_context = snapc; 382 realm->cached_context = snapc;
378 return 0; 383 return 0;
379 384
@@ -394,15 +399,16 @@ fail:
394/* 399/*
395 * rebuild snap context for the given realm and all of its children. 400 * rebuild snap context for the given realm and all of its children.
396 */ 401 */
397static void rebuild_snap_realms(struct ceph_snap_realm *realm) 402static void rebuild_snap_realms(struct ceph_snap_realm *realm,
403 struct list_head *dirty_realms)
398{ 404{
399 struct ceph_snap_realm *child; 405 struct ceph_snap_realm *child;
400 406
401 dout("rebuild_snap_realms %llx %p\n", realm->ino, realm); 407 dout("rebuild_snap_realms %llx %p\n", realm->ino, realm);
402 build_snap_context(realm); 408 build_snap_context(realm, dirty_realms);
403 409
404 list_for_each_entry(child, &realm->children, child_item) 410 list_for_each_entry(child, &realm->children, child_item)
405 rebuild_snap_realms(child); 411 rebuild_snap_realms(child, dirty_realms);
406} 412}
407 413
408 414
@@ -624,13 +630,11 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
624{ 630{
625 struct ceph_inode_info *ci; 631 struct ceph_inode_info *ci;
626 struct inode *lastinode = NULL; 632 struct inode *lastinode = NULL;
627 struct ceph_snap_realm *child;
628 633
629 dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino); 634 dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);
630 635
631 spin_lock(&realm->inodes_with_caps_lock); 636 spin_lock(&realm->inodes_with_caps_lock);
632 list_for_each_entry(ci, &realm->inodes_with_caps, 637 list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
633 i_snap_realm_item) {
634 struct inode *inode = igrab(&ci->vfs_inode); 638 struct inode *inode = igrab(&ci->vfs_inode);
635 if (!inode) 639 if (!inode)
636 continue; 640 continue;
@@ -643,14 +647,6 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
643 spin_unlock(&realm->inodes_with_caps_lock); 647 spin_unlock(&realm->inodes_with_caps_lock);
644 iput(lastinode); 648 iput(lastinode);
645 649
646 list_for_each_entry(child, &realm->children, child_item) {
647 dout("queue_realm_cap_snaps %p %llx queue child %p %llx\n",
648 realm, realm->ino, child, child->ino);
649 list_del_init(&child->dirty_item);
650 list_add(&child->dirty_item, &realm->dirty_item);
651 }
652
653 list_del_init(&realm->dirty_item);
654 dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino); 650 dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
655} 651}
656 652
@@ -721,8 +717,6 @@ more:
721 if (err < 0) 717 if (err < 0)
722 goto fail; 718 goto fail;
723 719
724 /* queue realm for cap_snap creation */
725 list_add(&realm->dirty_item, &dirty_realms);
726 if (realm->seq > mdsc->last_snap_seq) 720 if (realm->seq > mdsc->last_snap_seq)
727 mdsc->last_snap_seq = realm->seq; 721 mdsc->last_snap_seq = realm->seq;
728 722
@@ -741,7 +735,7 @@ more:
741 735
742 /* invalidate when we reach the _end_ (root) of the trace */ 736 /* invalidate when we reach the _end_ (root) of the trace */
743 if (invalidate && p >= e) 737 if (invalidate && p >= e)
744 rebuild_snap_realms(realm); 738 rebuild_snap_realms(realm, &dirty_realms);
745 739
746 if (!first_realm) 740 if (!first_realm)
747 first_realm = realm; 741 first_realm = realm;
@@ -758,6 +752,7 @@ more:
758 while (!list_empty(&dirty_realms)) { 752 while (!list_empty(&dirty_realms)) {
759 realm = list_first_entry(&dirty_realms, struct ceph_snap_realm, 753 realm = list_first_entry(&dirty_realms, struct ceph_snap_realm,
760 dirty_item); 754 dirty_item);
755 list_del_init(&realm->dirty_item);
761 queue_realm_cap_snaps(realm); 756 queue_realm_cap_snaps(realm);
762 } 757 }
763 758