Commit 3ae0bebc authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov

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: default avatar"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent c8fd0d37
...@@ -299,7 +299,8 @@ static int cmpu64_rev(const void *a, const void *b) ...@@ -299,7 +299,8 @@ static int cmpu64_rev(const void *a, const void *b)
/* /*
* build the snap context for a given realm. * 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_realm *parent = realm->parent;
struct ceph_snap_context *snapc; struct ceph_snap_context *snapc;
...@@ -313,7 +314,7 @@ static int build_snap_context(struct ceph_snap_realm *realm) ...@@ -313,7 +314,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
*/ */
if (parent) { if (parent) {
if (!parent->cached_context) { if (!parent->cached_context) {
err = build_snap_context(parent); err = build_snap_context(parent, dirty_realms);
if (err) if (err)
goto fail; goto fail;
} }
...@@ -332,7 +333,7 @@ static int build_snap_context(struct ceph_snap_realm *realm) ...@@ -332,7 +333,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
" (unchanged)\n", " (unchanged)\n",
realm->ino, realm, realm->cached_context, realm->ino, realm, realm->cached_context,
realm->cached_context->seq, realm->cached_context->seq,
(unsigned int) realm->cached_context->num_snaps); (unsigned int)realm->cached_context->num_snaps);
return 0; return 0;
} }
...@@ -373,7 +374,11 @@ static int build_snap_context(struct ceph_snap_realm *realm) ...@@ -373,7 +374,11 @@ static int build_snap_context(struct ceph_snap_realm *realm)
realm->ino, realm, snapc, snapc->seq, realm->ino, realm, snapc, snapc->seq,
(unsigned int) snapc->num_snaps); (unsigned int) snapc->num_snaps);
if (realm->cached_context) {
ceph_put_snap_context(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; realm->cached_context = snapc;
return 0; return 0;
...@@ -394,15 +399,16 @@ static int build_snap_context(struct ceph_snap_realm *realm) ...@@ -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. * 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; struct ceph_snap_realm *child;
dout("rebuild_snap_realms %llx %p\n", realm->ino, realm); 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) 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) ...@@ -624,13 +630,11 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
{ {
struct ceph_inode_info *ci; struct ceph_inode_info *ci;
struct inode *lastinode = NULL; struct inode *lastinode = NULL;
struct ceph_snap_realm *child;
dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino); dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);
spin_lock(&realm->inodes_with_caps_lock); spin_lock(&realm->inodes_with_caps_lock);
list_for_each_entry(ci, &realm->inodes_with_caps, list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
i_snap_realm_item) {
struct inode *inode = igrab(&ci->vfs_inode); struct inode *inode = igrab(&ci->vfs_inode);
if (!inode) if (!inode)
continue; continue;
...@@ -643,14 +647,6 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm) ...@@ -643,14 +647,6 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
spin_unlock(&realm->inodes_with_caps_lock); spin_unlock(&realm->inodes_with_caps_lock);
iput(lastinode); 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); dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
} }
...@@ -721,8 +717,6 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, ...@@ -721,8 +717,6 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
if (err < 0) if (err < 0)
goto fail; goto fail;
/* queue realm for cap_snap creation */
list_add(&realm->dirty_item, &dirty_realms);
if (realm->seq > mdsc->last_snap_seq) if (realm->seq > mdsc->last_snap_seq)
mdsc->last_snap_seq = realm->seq; mdsc->last_snap_seq = realm->seq;
...@@ -741,7 +735,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, ...@@ -741,7 +735,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
/* invalidate when we reach the _end_ (root) of the trace */ /* invalidate when we reach the _end_ (root) of the trace */
if (invalidate && p >= e) if (invalidate && p >= e)
rebuild_snap_realms(realm); rebuild_snap_realms(realm, &dirty_realms);
if (!first_realm) if (!first_realm)
first_realm = realm; first_realm = realm;
...@@ -758,6 +752,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, ...@@ -758,6 +752,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
while (!list_empty(&dirty_realms)) { while (!list_empty(&dirty_realms)) {
realm = list_first_entry(&dirty_realms, struct ceph_snap_realm, realm = list_first_entry(&dirty_realms, struct ceph_snap_realm,
dirty_item); dirty_item);
list_del_init(&realm->dirty_item);
queue_realm_cap_snaps(realm); queue_realm_cap_snaps(realm);
} }
......
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