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/ceph/snap.c | |
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/ceph/snap.c')
-rw-r--r-- | fs/ceph/snap.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 7e3e5f9edaa..d197431532c 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; |