Skip to content

Commit

Permalink
ceph: queue cap snap only when snap realm's context changes
Browse files Browse the repository at this point in the history
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" <[email protected]>
Signed-off-by: Ilya Dryomov <[email protected]>
  • Loading branch information
ukernel authored and idryomov committed Sep 6, 2017
1 parent c8fd0d3 commit 3ae0beb
Showing 1 changed file with 16 additions and 21 deletions.
37 changes: 16 additions & 21 deletions fs/ceph/snap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;

Expand All @@ -394,15 +399,16 @@ static int build_snap_context(struct ceph_snap_realm *realm)
/*
* 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);
}


Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down Expand Up @@ -721,8 +717,6 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
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;

Expand All @@ -741,7 +735,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,

/* 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;
Expand All @@ -758,6 +752,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
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);
}

Expand Down

0 comments on commit 3ae0beb

Please sign in to comment.