ceph: invalidate all write mode filp after reconnect
authorYan, Zheng <zyan@redhat.com>
Thu, 25 Jul 2019 12:16:46 +0000 (20:16 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 16 Sep 2019 10:06:24 +0000 (12:06 +0200)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/super.c
fs/ceph/super.h

index 102192c90edd96d213a54d6568567d0683e5c985..d17bde5d4f9a3cbab26f349c0bc14ffb7fb1b3b0 100644 (file)
@@ -2780,12 +2780,17 @@ int ceph_get_caps(struct file *filp, int need, int want,
        struct ceph_file_info *fi = filp->private_data;
        struct inode *inode = file_inode(filp);
        struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        int ret, _got, flags;
 
        ret = ceph_pool_perm_check(inode, need);
        if (ret < 0)
                return ret;
 
+       if ((fi->fmode & CEPH_FILE_MODE_WR) &&
+           fi->filp_gen != READ_ONCE(fsc->filp_gen))
+               return -EBADF;
+
        while (true) {
                if (endoff > 0)
                        check_max_size(inode, endoff);
@@ -2814,6 +2819,14 @@ int ceph_get_caps(struct file *filp, int need, int want,
                        if (ret == -EAGAIN)
                                continue;
                }
+
+               if ((fi->fmode & CEPH_FILE_MODE_WR) &&
+                   fi->filp_gen != READ_ONCE(fsc->filp_gen)) {
+                       if (ret >= 0 && _got)
+                               ceph_put_cap_refs(ci, _got);
+                       return -EBADF;
+               }
+
                if (ret < 0) {
                        if (ret == -ESTALE) {
                                /* session was killed, try renew caps */
index fb007b75fb179a040682fc03adbd509ec2529bef..779bf68afd601ce73008780f166d6467a5ad77f7 100644 (file)
@@ -234,6 +234,7 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
        spin_lock_init(&fi->rw_contexts_lock);
        INIT_LIST_HEAD(&fi->rw_contexts);
        fi->meta_err = errseq_sample(&ci->i_meta_err);
+       fi->filp_gen = READ_ONCE(ceph_inode_to_client(inode)->filp_gen);
 
        return 0;
 }
index a95dd13bb628c4324c3853be7ab7800e43115205..630549ac4f48b5b9870583bc17cb0006eec68bb3 100644 (file)
@@ -664,6 +664,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
 
        fsc->sb = NULL;
        fsc->mount_state = CEPH_MOUNT_MOUNTING;
+       fsc->filp_gen = 1;
 
        atomic_long_set(&fsc->writeback_count, 0);
 
@@ -829,6 +830,7 @@ static void ceph_umount_begin(struct super_block *sb)
        fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
        ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
        ceph_mdsc_force_umount(fsc->mdsc);
+       fsc->filp_gen++; // invalidate open files
 }
 
 static int ceph_remount(struct super_block *sb, int *flags, char *data)
index 736318210bc94fc98d033a82e795c5f05027ef5c..f5e5f6a6bfb8f33137b93eb67f2f8018b616c141 100644 (file)
@@ -101,6 +101,8 @@ struct ceph_fs_client {
        struct ceph_client *client;
 
        unsigned long mount_state;
+
+       u32 filp_gen;
        loff_t max_file_size;
 
        struct ceph_mds_client *mdsc;
@@ -707,6 +709,7 @@ struct ceph_file_info {
        struct list_head rw_contexts;
 
        errseq_t meta_err;
+       u32 filp_gen;
        atomic_t num_locks;
 };