diff options
author | Sage Weil <sage@newdream.net> | 2010-04-13 14:41:22 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-04-13 15:28:31 -0400 |
commit | fc837c8f0446b73a1661339db406c0238dd1d184 (patch) | |
tree | 5cc1e6b97a8f39f7979eb302ac8a090c812f2609 /fs | |
parent | f5b066287c74b624583b993395a65d03a6487b3a (diff) |
ceph: queue_cap_snap should always queue dirty context
This simplifies the calling convention, and fixes a bug where we queue a
capsnap with a context other than i_head_snapc (the one that matches the
dirty pages). The result was a BUG at fs/ceph/caps.c:2178 on writeback
completion when a capsnap matching the writeback snapc could not be found.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/snap.c | 16 | ||||
-rw-r--r-- | fs/ceph/super.h | 3 |
2 files changed, 8 insertions, 11 deletions
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 7e3e5f9edaa4..d197431532c0 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -430,8 +430,7 @@ static int dup_array(u64 **dst, __le64 *src, int num) | |||
430 | * Caller must hold snap_rwsem for read (i.e., the realm topology won't | 430 | * Caller must hold snap_rwsem for read (i.e., the realm topology won't |
431 | * change). | 431 | * change). |
432 | */ | 432 | */ |
433 | void ceph_queue_cap_snap(struct ceph_inode_info *ci, | 433 | void ceph_queue_cap_snap(struct ceph_inode_info *ci) |
434 | struct ceph_snap_context *snapc) | ||
435 | { | 434 | { |
436 | struct inode *inode = &ci->vfs_inode; | 435 | struct inode *inode = &ci->vfs_inode; |
437 | struct ceph_cap_snap *capsnap; | 436 | struct ceph_cap_snap *capsnap; |
@@ -450,10 +449,11 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, | |||
450 | as no new writes are allowed to start when pending, so any | 449 | as no new writes are allowed to start when pending, so any |
451 | writes in progress now were started before the previous | 450 | writes in progress now were started before the previous |
452 | cap_snap. lucky us. */ | 451 | cap_snap. lucky us. */ |
453 | dout("queue_cap_snap %p snapc %p seq %llu used %d" | 452 | dout("queue_cap_snap %p already pending\n", inode); |
454 | " already pending\n", inode, snapc, snapc->seq, used); | ||
455 | kfree(capsnap); | 453 | kfree(capsnap); |
456 | } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) { | 454 | } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) { |
455 | struct ceph_snap_context *snapc = ci->i_head_snapc; | ||
456 | |||
457 | igrab(inode); | 457 | igrab(inode); |
458 | 458 | ||
459 | atomic_set(&capsnap->nref, 1); | 459 | atomic_set(&capsnap->nref, 1); |
@@ -462,7 +462,6 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, | |||
462 | INIT_LIST_HEAD(&capsnap->flushing_item); | 462 | INIT_LIST_HEAD(&capsnap->flushing_item); |
463 | 463 | ||
464 | capsnap->follows = snapc->seq - 1; | 464 | capsnap->follows = snapc->seq - 1; |
465 | capsnap->context = ceph_get_snap_context(snapc); | ||
466 | capsnap->issued = __ceph_caps_issued(ci, NULL); | 465 | capsnap->issued = __ceph_caps_issued(ci, NULL); |
467 | capsnap->dirty = __ceph_caps_dirty(ci); | 466 | capsnap->dirty = __ceph_caps_dirty(ci); |
468 | 467 | ||
@@ -479,7 +478,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, | |||
479 | snapshot. */ | 478 | snapshot. */ |
480 | capsnap->dirty_pages = ci->i_wrbuffer_ref_head; | 479 | capsnap->dirty_pages = ci->i_wrbuffer_ref_head; |
481 | ci->i_wrbuffer_ref_head = 0; | 480 | ci->i_wrbuffer_ref_head = 0; |
482 | ceph_put_snap_context(ci->i_head_snapc); | 481 | capsnap->context = snapc; |
483 | ci->i_head_snapc = NULL; | 482 | ci->i_head_snapc = NULL; |
484 | list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps); | 483 | list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps); |
485 | 484 | ||
@@ -603,7 +602,7 @@ more: | |||
603 | if (lastinode) | 602 | if (lastinode) |
604 | iput(lastinode); | 603 | iput(lastinode); |
605 | lastinode = inode; | 604 | lastinode = inode; |
606 | ceph_queue_cap_snap(ci, realm->cached_context); | 605 | ceph_queue_cap_snap(ci); |
607 | spin_lock(&realm->inodes_with_caps_lock); | 606 | spin_lock(&realm->inodes_with_caps_lock); |
608 | } | 607 | } |
609 | spin_unlock(&realm->inodes_with_caps_lock); | 608 | spin_unlock(&realm->inodes_with_caps_lock); |
@@ -825,8 +824,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, | |||
825 | spin_unlock(&realm->inodes_with_caps_lock); | 824 | spin_unlock(&realm->inodes_with_caps_lock); |
826 | spin_unlock(&inode->i_lock); | 825 | spin_unlock(&inode->i_lock); |
827 | 826 | ||
828 | ceph_queue_cap_snap(ci, | 827 | ceph_queue_cap_snap(ci); |
829 | ci->i_snap_realm->cached_context); | ||
830 | 828 | ||
831 | iput(inode); | 829 | iput(inode); |
832 | continue; | 830 | continue; |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 65d12036b670..4c07acaf21e3 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -714,8 +714,7 @@ extern int ceph_update_snap_trace(struct ceph_mds_client *m, | |||
714 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, | 714 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, |
715 | struct ceph_mds_session *session, | 715 | struct ceph_mds_session *session, |
716 | struct ceph_msg *msg); | 716 | struct ceph_msg *msg); |
717 | extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, | 717 | extern void ceph_queue_cap_snap(struct ceph_inode_info *ci); |
718 | struct ceph_snap_context *snapc); | ||
719 | extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, | 718 | extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, |
720 | struct ceph_cap_snap *capsnap); | 719 | struct ceph_cap_snap *capsnap); |
721 | extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); | 720 | extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); |