Merge tag 'fixes-for-v3.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
[cascardo/linux.git] / fs / ceph / caps.c
index a1d9bb3..78e2f57 100644 (file)
@@ -611,8 +611,16 @@ retry:
 
        if (flags & CEPH_CAP_FLAG_AUTH)
                ci->i_auth_cap = cap;
-       else if (ci->i_auth_cap == cap)
+       else if (ci->i_auth_cap == cap) {
                ci->i_auth_cap = NULL;
+               spin_lock(&mdsc->cap_dirty_lock);
+               if (!list_empty(&ci->i_dirty_item)) {
+                       dout(" moving %p to cap_dirty_migrating\n", inode);
+                       list_move(&ci->i_dirty_item,
+                                 &mdsc->cap_dirty_migrating);
+               }
+               spin_unlock(&mdsc->cap_dirty_lock);
+       }
 
        dout("add_cap inode %p (%llx.%llx) cap %p %s now %s seq %d mds%d\n",
             inode, ceph_vinop(inode), cap, ceph_cap_string(issued),
@@ -930,7 +938,7 @@ static int send_cap_msg(struct ceph_mds_session *session,
                        u64 size, u64 max_size,
                        struct timespec *mtime, struct timespec *atime,
                        u64 time_warp_seq,
-                       uid_t uid, gid_t gid, umode_t mode,
+                       kuid_t uid, kgid_t gid, umode_t mode,
                        u64 xattr_version,
                        struct ceph_buffer *xattrs_buf,
                        u64 follows)
@@ -974,8 +982,8 @@ static int send_cap_msg(struct ceph_mds_session *session,
                ceph_encode_timespec(&fc->atime, atime);
        fc->time_warp_seq = cpu_to_le32(time_warp_seq);
 
-       fc->uid = cpu_to_le32(uid);
-       fc->gid = cpu_to_le32(gid);
+       fc->uid = cpu_to_le32(from_kuid(&init_user_ns, uid));
+       fc->gid = cpu_to_le32(from_kgid(&init_user_ns, gid));
        fc->mode = cpu_to_le32(mode);
 
        fc->xattr_version = cpu_to_le64(xattr_version);
@@ -1081,8 +1089,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        struct timespec mtime, atime;
        int wake = 0;
        umode_t mode;
-       uid_t uid;
-       gid_t gid;
+       kuid_t uid;
+       kgid_t gid;
        struct ceph_mds_session *session;
        u64 xattr_version = 0;
        struct ceph_buffer *xattr_blob = NULL;
@@ -1460,7 +1468,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
        struct ceph_mds_client *mdsc = fsc->mdsc;
        struct inode *inode = &ci->vfs_inode;
        struct ceph_cap *cap;
-       int file_wanted, used;
+       int file_wanted, used, cap_used;
        int took_snap_rwsem = 0;             /* true if mdsc->snap_rwsem held */
        int issued, implemented, want, retain, revoking, flushing = 0;
        int mds = -1;   /* keep track of how far we've gone through i_caps list
@@ -1563,9 +1571,14 @@ retry_locked:
 
                /* NOTE: no side-effects allowed, until we take s_mutex */
 
+               cap_used = used;
+               if (ci->i_auth_cap && cap != ci->i_auth_cap)
+                       cap_used &= ~ci->i_auth_cap->issued;
+
                revoking = cap->implemented & ~cap->issued;
-               dout(" mds%d cap %p issued %s implemented %s revoking %s\n",
+               dout(" mds%d cap %p used %s issued %s implemented %s revoking %s\n",
                     cap->mds, cap, ceph_cap_string(cap->issued),
+                    ceph_cap_string(cap_used),
                     ceph_cap_string(cap->implemented),
                     ceph_cap_string(revoking));
 
@@ -1593,7 +1606,7 @@ retry_locked:
                }
 
                /* completed revocation? going down and there are no caps? */
-               if (revoking && (revoking & used) == 0) {
+               if (revoking && (revoking & cap_used) == 0) {
                        dout("completed revocation of %s\n",
                             ceph_cap_string(cap->implemented & ~cap->issued));
                        goto ack;
@@ -1670,8 +1683,8 @@ ack:
                sent++;
 
                /* __send_cap drops i_ceph_lock */
-               delayed += __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, used, want,
-                                     retain, flushing, NULL);
+               delayed += __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, cap_used,
+                                     want, retain, flushing, NULL);
                goto retry; /* retake i_ceph_lock and restart our cap scan. */
        }
 
@@ -2359,10 +2372,11 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
 
        if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
                inode->i_mode = le32_to_cpu(grant->mode);
-               inode->i_uid = le32_to_cpu(grant->uid);
-               inode->i_gid = le32_to_cpu(grant->gid);
+               inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
+               inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
                dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
-                    inode->i_uid, inode->i_gid);
+                    from_kuid(&init_user_ns, inode->i_uid),
+                    from_kgid(&init_user_ns, inode->i_gid));
        }
 
        if ((issued & CEPH_CAP_LINK_EXCL) == 0)
@@ -2416,7 +2430,9 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                dout("mds wanted %s -> %s\n",
                     ceph_cap_string(le32_to_cpu(grant->wanted)),
                     ceph_cap_string(wanted));
-               grant->wanted = cpu_to_le32(wanted);
+               /* imported cap may not have correct mds_wanted */
+               if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT)
+                       check_caps = 1;
        }
 
        cap->seq = seq;
@@ -2820,6 +2836,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        dout(" mds%d seq %lld cap seq %u\n", session->s_mds, session->s_seq,
             (unsigned)seq);
 
+       if (op == CEPH_CAP_OP_IMPORT)
+               ceph_add_cap_releases(mdsc, session);
+
        /* lookup ino */
        inode = ceph_find_inode(sb, vino);
        ci = ceph_inode(inode);