ceph: ensure d_name/d_parent stability in ceph_mdsc_lease_send_msg()
authorYan, Zheng <zyan@redhat.com>
Thu, 23 May 2019 02:45:24 +0000 (10:45 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 8 Jul 2019 12:01:42 +0000 (14:01 +0200)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/dir.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h

index 1271024..72efad2 100644 (file)
@@ -1433,8 +1433,7 @@ static bool __dentry_lease_is_valid(struct ceph_dentry_info *di)
        return false;
 }
 
-static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
-                                struct inode *dir)
+static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags)
 {
        struct ceph_dentry_info *di;
        struct ceph_mds_session *session = NULL;
@@ -1466,7 +1465,7 @@ static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
        spin_unlock(&dentry->d_lock);
 
        if (session) {
-               ceph_mdsc_lease_send_msg(session, dir, dentry,
+               ceph_mdsc_lease_send_msg(session, dentry,
                                         CEPH_MDS_LEASE_RENEW, seq);
                ceph_put_mds_session(session);
        }
@@ -1566,7 +1565,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
                   ceph_snap(d_inode(dentry)) == CEPH_SNAPDIR) {
                valid = 1;
        } else {
-               valid = dentry_lease_is_valid(dentry, flags, dir);
+               valid = dentry_lease_is_valid(dentry, flags);
                if (valid == -ECHILD)
                        return valid;
                if (valid || dir_lease_is_valid(dir, dentry)) {
index 88bc68d..709ac3b 100644 (file)
@@ -3941,31 +3941,33 @@ bad:
 }
 
 void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
-                             struct inode *inode,
                              struct dentry *dentry, char action,
                              u32 seq)
 {
        struct ceph_msg *msg;
        struct ceph_mds_lease *lease;
-       int len = sizeof(*lease) + sizeof(u32);
-       int dnamelen = 0;
+       struct inode *dir;
+       int len = sizeof(*lease) + sizeof(u32) + NAME_MAX;
 
-       dout("lease_send_msg inode %p dentry %p %s to mds%d\n",
-            inode, dentry, ceph_lease_op_name(action), session->s_mds);
-       dnamelen = dentry->d_name.len;
-       len += dnamelen;
+       dout("lease_send_msg identry %p %s to mds%d\n",
+            dentry, ceph_lease_op_name(action), session->s_mds);
 
        msg = ceph_msg_new(CEPH_MSG_CLIENT_LEASE, len, GFP_NOFS, false);
        if (!msg)
                return;
        lease = msg->front.iov_base;
        lease->action = action;
-       lease->ino = cpu_to_le64(ceph_vino(inode).ino);
-       lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap);
        lease->seq = cpu_to_le32(seq);
-       put_unaligned_le32(dnamelen, lease + 1);
-       memcpy((void *)(lease + 1) + 4, dentry->d_name.name, dnamelen);
 
+       spin_lock(&dentry->d_lock);
+       dir = d_inode(dentry->d_parent);
+       lease->ino = cpu_to_le64(ceph_ino(dir));
+       lease->first = lease->last = cpu_to_le64(ceph_snap(dir));
+
+       put_unaligned_le32(dentry->d_name.len, lease + 1);
+       memcpy((void *)(lease + 1) + 4,
+              dentry->d_name.name, dentry->d_name.len);
+       spin_unlock(&dentry->d_lock);
        /*
         * if this is a preemptive lease RELEASE, no need to
         * flush request stream, since the actual request will
index 9c28b86..330769e 100644 (file)
@@ -505,7 +505,6 @@ extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
 
 extern void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry);
 extern void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
-                                    struct inode *inode,
                                     struct dentry *dentry, char action,
                                     u32 seq);