ceph: fix incorrect snaprealm when adding caps
authorYan, Zheng <zyan@redhat.com>
Tue, 19 Dec 2017 10:00:54 +0000 (18:00 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 29 Jan 2018 17:36:09 +0000 (18:36 +0100)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/snap.c

index 57120e3..7e09fa8 100644 (file)
@@ -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);
index 8a2ca41..07cf95e 100644 (file)
@@ -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);