aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-04-13 14:41:22 -0400
committerSage Weil <sage@newdream.net>2010-04-13 15:28:31 -0400
commitfc837c8f0446b73a1661339db406c0238dd1d184 (patch)
tree5cc1e6b97a8f39f7979eb302ac8a090c812f2609 /fs/ceph
parentf5b066287c74b624583b993395a65d03a6487b3a (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')
-rw-r--r--fs/ceph/snap.c16
-rw-r--r--fs/ceph/super.h3
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 */
433void ceph_queue_cap_snap(struct ceph_inode_info *ci, 433void 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,
714extern void ceph_handle_snap(struct ceph_mds_client *mdsc, 714extern 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);
717extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, 717extern void ceph_queue_cap_snap(struct ceph_inode_info *ci);
718 struct ceph_snap_context *snapc);
719extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, 718extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
720 struct ceph_cap_snap *capsnap); 719 struct ceph_cap_snap *capsnap);
721extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); 720extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc);