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>
This commit is contained in:
parent
c8fd0d37f8
commit
3ae0bebc49
1 changed files with 16 additions and 21 deletions
|
@ -299,7 +299,8 @@ static int cmpu64_rev(const void *a, const void *b)
|
|||
/*
|
||||
* build the snap context for a given realm.
|
||||
*/
|
||||
static int build_snap_context(struct ceph_snap_realm *realm)
|
||||
static int build_snap_context(struct ceph_snap_realm *realm,
|
||||
struct list_head* dirty_realms)
|
||||
{
|
||||
struct ceph_snap_realm *parent = realm->parent;
|
||||
struct ceph_snap_context *snapc;
|
||||
|
@ -313,7 +314,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
|
|||
*/
|
||||
if (parent) {
|
||||
if (!parent->cached_context) {
|
||||
err = build_snap_context(parent);
|
||||
err = build_snap_context(parent, dirty_realms);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -332,7 +333,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
|
|||
" (unchanged)\n",
|
||||
realm->ino, realm, realm->cached_context,
|
||||
realm->cached_context->seq,
|
||||
(unsigned int) realm->cached_context->num_snaps);
|
||||
(unsigned int)realm->cached_context->num_snaps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -373,7 +374,11 @@ static int build_snap_context(struct ceph_snap_realm *realm)
|
|||
realm->ino, realm, snapc, snapc->seq,
|
||||
(unsigned int) snapc->num_snaps);
|
||||
|
||||
ceph_put_snap_context(realm->cached_context);
|
||||
if (realm->cached_context) {
|
||||
ceph_put_snap_context(realm->cached_context);
|
||||
/* queue realm for cap_snap creation */
|
||||
list_add_tail(&realm->dirty_item, dirty_realms);
|
||||
}
|
||||
realm->cached_context = snapc;
|
||||
return 0;
|
||||
|
||||
|
@ -394,15 +399,16 @@ fail:
|
|||
/*
|
||||
* rebuild snap context for the given realm and all of its children.
|
||||
*/
|
||||
static void rebuild_snap_realms(struct ceph_snap_realm *realm)
|
||||
static void rebuild_snap_realms(struct ceph_snap_realm *realm,
|
||||
struct list_head *dirty_realms)
|
||||
{
|
||||
struct ceph_snap_realm *child;
|
||||
|
||||
dout("rebuild_snap_realms %llx %p\n", realm->ino, realm);
|
||||
build_snap_context(realm);
|
||||
build_snap_context(realm, dirty_realms);
|
||||
|
||||
list_for_each_entry(child, &realm->children, child_item)
|
||||
rebuild_snap_realms(child);
|
||||
rebuild_snap_realms(child, dirty_realms);
|
||||
}
|
||||
|
||||
|
||||
|
@ -624,13 +630,11 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
|
|||
{
|
||||
struct ceph_inode_info *ci;
|
||||
struct inode *lastinode = NULL;
|
||||
struct ceph_snap_realm *child;
|
||||
|
||||
dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);
|
||||
|
||||
spin_lock(&realm->inodes_with_caps_lock);
|
||||
list_for_each_entry(ci, &realm->inodes_with_caps,
|
||||
i_snap_realm_item) {
|
||||
list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
|
||||
struct inode *inode = igrab(&ci->vfs_inode);
|
||||
if (!inode)
|
||||
continue;
|
||||
|
@ -643,14 +647,6 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
|
|||
spin_unlock(&realm->inodes_with_caps_lock);
|
||||
iput(lastinode);
|
||||
|
||||
list_for_each_entry(child, &realm->children, child_item) {
|
||||
dout("queue_realm_cap_snaps %p %llx queue child %p %llx\n",
|
||||
realm, realm->ino, child, child->ino);
|
||||
list_del_init(&child->dirty_item);
|
||||
list_add(&child->dirty_item, &realm->dirty_item);
|
||||
}
|
||||
|
||||
list_del_init(&realm->dirty_item);
|
||||
dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
|
||||
}
|
||||
|
||||
|
@ -721,8 +717,6 @@ more:
|
|||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
/* queue realm for cap_snap creation */
|
||||
list_add(&realm->dirty_item, &dirty_realms);
|
||||
if (realm->seq > mdsc->last_snap_seq)
|
||||
mdsc->last_snap_seq = realm->seq;
|
||||
|
||||
|
@ -741,7 +735,7 @@ more:
|
|||
|
||||
/* invalidate when we reach the _end_ (root) of the trace */
|
||||
if (invalidate && p >= e)
|
||||
rebuild_snap_realms(realm);
|
||||
rebuild_snap_realms(realm, &dirty_realms);
|
||||
|
||||
if (!first_realm)
|
||||
first_realm = realm;
|
||||
|
@ -758,6 +752,7 @@ more:
|
|||
while (!list_empty(&dirty_realms)) {
|
||||
realm = list_first_entry(&dirty_realms, struct ceph_snap_realm,
|
||||
dirty_item);
|
||||
list_del_init(&realm->dirty_item);
|
||||
queue_realm_cap_snaps(realm);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue