summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2017-12-19 11:00:54 +0100
committerIlya Dryomov <idryomov@gmail.com>2018-01-29 18:36:09 +0100
commit7d9c9193b5d0b1b806f453a3baa9bfe7e6fac52d (patch)
treec25913f90e6e3af08160c72b9018afe0726effa2 /fs
parentceph: fix un-balanced fsc->writeback_count update (diff)
downloadlinux-7d9c9193b5d0b1b806f453a3baa9bfe7e6fac52d.tar.xz
linux-7d9c9193b5d0b1b806f453a3baa9bfe7e6fac52d.zip
ceph: fix incorrect snaprealm when adding caps
Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/caps.c14
-rw-r--r--fs/ceph/snap.c8
2 files changed, 19 insertions, 3 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 57120e3d44de..7e09fa8ab0ed 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -577,18 +577,30 @@ void ceph_add_cap(struct inode *inode,
}
}
- if (!ci->i_snap_realm) {
+ if (!ci->i_snap_realm ||
+ ((flags & CEPH_CAP_FLAG_AUTH) &&
+ realmino != (u64)-1 && ci->i_snap_realm->ino != realmino)) {
/*
* add this inode to the appropriate snap realm
*/
struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc,
realmino);
if (realm) {
+ struct ceph_snap_realm *oldrealm = ci->i_snap_realm;
+ if (oldrealm) {
+ spin_lock(&oldrealm->inodes_with_caps_lock);
+ list_del_init(&ci->i_snap_realm_item);
+ spin_unlock(&oldrealm->inodes_with_caps_lock);
+ }
+
spin_lock(&realm->inodes_with_caps_lock);
ci->i_snap_realm = realm;
list_add(&ci->i_snap_realm_item,
&realm->inodes_with_caps);
spin_unlock(&realm->inodes_with_caps_lock);
+
+ if (oldrealm)
+ ceph_put_snap_realm(mdsc, oldrealm);
} else {
pr_err("ceph_add_cap: couldn't find snap realm %llx\n",
realmino);
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 8a2ca41e4b97..07cf95e6413d 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -922,13 +922,17 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
/*
* Move the inode to the new realm
*/
- spin_lock(&realm->inodes_with_caps_lock);
+ oldrealm = ci->i_snap_realm;
+ spin_lock(&oldrealm->inodes_with_caps_lock);
list_del_init(&ci->i_snap_realm_item);
+ spin_unlock(&oldrealm->inodes_with_caps_lock);
+
+ spin_lock(&realm->inodes_with_caps_lock);
list_add(&ci->i_snap_realm_item,
&realm->inodes_with_caps);
- oldrealm = ci->i_snap_realm;
ci->i_snap_realm = realm;
spin_unlock(&realm->inodes_with_caps_lock);
+
spin_unlock(&ci->i_ceph_lock);
ceph_get_snap_realm(mdsc, realm);