Commit fc837c8f authored by Sage Weil's avatar Sage Weil

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: default avatarSage Weil <sage@newdream.net>
parent f5b06628
...@@ -430,8 +430,7 @@ static int dup_array(u64 **dst, __le64 *src, int num) ...@@ -430,8 +430,7 @@ static int dup_array(u64 **dst, __le64 *src, int num)
* Caller must hold snap_rwsem for read (i.e., the realm topology won't * Caller must hold snap_rwsem for read (i.e., the realm topology won't
* change). * change).
*/ */
void ceph_queue_cap_snap(struct ceph_inode_info *ci, void ceph_queue_cap_snap(struct ceph_inode_info *ci)
struct ceph_snap_context *snapc)
{ {
struct inode *inode = &ci->vfs_inode; struct inode *inode = &ci->vfs_inode;
struct ceph_cap_snap *capsnap; struct ceph_cap_snap *capsnap;
...@@ -450,10 +449,11 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, ...@@ -450,10 +449,11 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci,
as no new writes are allowed to start when pending, so any as no new writes are allowed to start when pending, so any
writes in progress now were started before the previous writes in progress now were started before the previous
cap_snap. lucky us. */ cap_snap. lucky us. */
dout("queue_cap_snap %p snapc %p seq %llu used %d" dout("queue_cap_snap %p already pending\n", inode);
" already pending\n", inode, snapc, snapc->seq, used);
kfree(capsnap); kfree(capsnap);
} else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) { } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) {
struct ceph_snap_context *snapc = ci->i_head_snapc;
igrab(inode); igrab(inode);
atomic_set(&capsnap->nref, 1); atomic_set(&capsnap->nref, 1);
...@@ -462,7 +462,6 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, ...@@ -462,7 +462,6 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci,
INIT_LIST_HEAD(&capsnap->flushing_item); INIT_LIST_HEAD(&capsnap->flushing_item);
capsnap->follows = snapc->seq - 1; capsnap->follows = snapc->seq - 1;
capsnap->context = ceph_get_snap_context(snapc);
capsnap->issued = __ceph_caps_issued(ci, NULL); capsnap->issued = __ceph_caps_issued(ci, NULL);
capsnap->dirty = __ceph_caps_dirty(ci); capsnap->dirty = __ceph_caps_dirty(ci);
...@@ -479,7 +478,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci, ...@@ -479,7 +478,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci,
snapshot. */ snapshot. */
capsnap->dirty_pages = ci->i_wrbuffer_ref_head; capsnap->dirty_pages = ci->i_wrbuffer_ref_head;
ci->i_wrbuffer_ref_head = 0; ci->i_wrbuffer_ref_head = 0;
ceph_put_snap_context(ci->i_head_snapc); capsnap->context = snapc;
ci->i_head_snapc = NULL; ci->i_head_snapc = NULL;
list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps); list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps);
...@@ -603,7 +602,7 @@ more: ...@@ -603,7 +602,7 @@ more:
if (lastinode) if (lastinode)
iput(lastinode); iput(lastinode);
lastinode = inode; lastinode = inode;
ceph_queue_cap_snap(ci, realm->cached_context); ceph_queue_cap_snap(ci);
spin_lock(&realm->inodes_with_caps_lock); spin_lock(&realm->inodes_with_caps_lock);
} }
spin_unlock(&realm->inodes_with_caps_lock); spin_unlock(&realm->inodes_with_caps_lock);
...@@ -825,8 +824,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, ...@@ -825,8 +824,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
spin_unlock(&realm->inodes_with_caps_lock); spin_unlock(&realm->inodes_with_caps_lock);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
ceph_queue_cap_snap(ci, ceph_queue_cap_snap(ci);
ci->i_snap_realm->cached_context);
iput(inode); iput(inode);
continue; continue;
......
...@@ -714,8 +714,7 @@ extern int ceph_update_snap_trace(struct ceph_mds_client *m, ...@@ -714,8 +714,7 @@ extern int ceph_update_snap_trace(struct ceph_mds_client *m,
extern void ceph_handle_snap(struct ceph_mds_client *mdsc, extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session, struct ceph_mds_session *session,
struct ceph_msg *msg); struct ceph_msg *msg);
extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, extern void ceph_queue_cap_snap(struct ceph_inode_info *ci);
struct ceph_snap_context *snapc);
extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
struct ceph_cap_snap *capsnap); struct ceph_cap_snap *capsnap);
extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment