libceph, ceph: implement msgr2.1 protocol (crc and secure modes)
[linux-2.6-microblaze.git] / fs / ceph / inode.c
index 526faf4..adc8fc3 100644 (file)
@@ -1315,15 +1315,10 @@ retry_lookup:
        }
 
        if (rinfo->head->is_target) {
-               tvino.ino = le64_to_cpu(rinfo->targeti.in->ino);
-               tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
-
-               in = ceph_get_inode(sb, tvino);
-               if (IS_ERR(in)) {
-                       err = PTR_ERR(in);
-                       goto done;
-               }
+               /* Should be filled in by handle_reply */
+               BUG_ON(!req->r_target_inode);
 
+               in = req->r_target_inode;
                err = ceph_fill_inode(in, req->r_locked_page, &rinfo->targeti,
                                NULL, session,
                                (!test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags) &&
@@ -1333,11 +1328,13 @@ retry_lookup:
                if (err < 0) {
                        pr_err("ceph_fill_inode badness %p %llx.%llx\n",
                                in, ceph_vinop(in));
+                       req->r_target_inode = NULL;
                        if (in->i_state & I_NEW)
                                discard_new_inode(in);
+                       else
+                               iput(in);
                        goto done;
                }
-               req->r_target_inode = in;
                if (in->i_state & I_NEW)
                        unlock_new_inode(in);
        }
@@ -1597,8 +1594,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
        struct dentry *dn;
        struct inode *in;
        int err = 0, skipped = 0, ret, i;
-       struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
-       u32 frag = le32_to_cpu(rhead->args.readdir.frag);
+       u32 frag = le32_to_cpu(req->r_args.readdir.frag);
        u32 last_hash = 0;
        u32 fpos_offset;
        struct ceph_readdir_cache_control cache_ctl = {};
@@ -1615,7 +1611,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                } else if (rinfo->offset_hash) {
                        /* mds understands offset_hash */
                        WARN_ON_ONCE(req->r_readdir_offset != 2);
-                       last_hash = le32_to_cpu(rhead->args.readdir.offset_hash);
+                       last_hash = le32_to_cpu(req->r_args.readdir.offset_hash);
                }
        }
 
@@ -1888,7 +1884,7 @@ static void ceph_do_invalidate_pages(struct inode *inode)
 
        mutex_lock(&ci->i_truncate_mutex);
 
-       if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
+       if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
                pr_warn_ratelimited("invalidate_pages %p %lld forced umount\n",
                                    inode, ceph_ino(inode));
                mapping_set_error(inode->i_mapping, -EIO);
@@ -2340,15 +2336,23 @@ int ceph_permission(struct inode *inode, int mask)
 }
 
 /* Craft a mask of needed caps given a set of requested statx attrs. */
-static int statx_to_caps(u32 want)
+static int statx_to_caps(u32 want, umode_t mode)
 {
        int mask = 0;
 
        if (want & (STATX_MODE|STATX_UID|STATX_GID|STATX_CTIME|STATX_BTIME))
                mask |= CEPH_CAP_AUTH_SHARED;
 
-       if (want & (STATX_NLINK|STATX_CTIME))
-               mask |= CEPH_CAP_LINK_SHARED;
+       if (want & (STATX_NLINK|STATX_CTIME)) {
+               /*
+                * The link count for directories depends on inode->i_subdirs,
+                * and that is only updated when Fs caps are held.
+                */
+               if (S_ISDIR(mode))
+                       mask |= CEPH_CAP_FILE_SHARED;
+               else
+                       mask |= CEPH_CAP_LINK_SHARED;
+       }
 
        if (want & (STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_SIZE|
                    STATX_BLOCKS))
@@ -2374,8 +2378,9 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
 
        /* Skip the getattr altogether if we're asked not to sync */
        if (!(flags & AT_STATX_DONT_SYNC)) {
-               err = ceph_do_getattr(inode, statx_to_caps(request_mask),
-                                     flags & AT_STATX_FORCE_SYNC);
+               err = ceph_do_getattr(inode,
+                               statx_to_caps(request_mask, inode->i_mode),
+                               flags & AT_STATX_FORCE_SYNC);
                if (err)
                        return err;
        }