ceph: check inode type for CEPH_CAP_FILE_{CACHE,RD,REXTEND,LAZYIO}
authorYan, Zheng <zyan@redhat.com>
Sat, 11 May 2019 09:27:59 +0000 (17:27 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 30 Mar 2020 10:42:40 +0000 (12:42 +0200)
These bits will have new meaning for directory inodes.

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/mds_client.c
fs/ceph/super.h

index 1a17f19..d057173 100644 (file)
@@ -573,7 +573,8 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
         * Each time we receive FILE_CACHE anew, we increment
         * i_rdcache_gen.
         */
-       if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
+       if (S_ISREG(ci->vfs_inode.i_mode) &&
+           (issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
            (had & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0) {
                ci->i_rdcache_gen++;
        }
@@ -958,7 +959,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci)
        if (ci->i_rd_ref)
                used |= CEPH_CAP_FILE_RD;
        if (ci->i_rdcache_ref ||
-           (!S_ISDIR(ci->vfs_inode.i_mode) && /* ignore readdir cache */
+           (S_ISREG(ci->vfs_inode.i_mode) &&
             ci->vfs_inode.i_data.nrpages))
                used |= CEPH_CAP_FILE_CACHE;
        if (ci->i_wr_ref)
@@ -985,6 +986,20 @@ int __ceph_caps_file_wanted(struct ceph_inode_info *ci)
        return ceph_caps_for_mode(bits >> 1);
 }
 
+/*
+ * wanted, by virtue of open file modes AND cap refs (buffered/cached data)
+ */
+int __ceph_caps_wanted(struct ceph_inode_info *ci)
+{
+       int w = __ceph_caps_file_wanted(ci) | __ceph_caps_used(ci);
+       if (!S_ISDIR(ci->vfs_inode.i_mode)) {
+               /* we want EXCL if dirty data */
+               if (w & CEPH_CAP_FILE_BUFFER)
+                       w |= CEPH_CAP_FILE_EXCL;
+       }
+       return w;
+}
+
 /*
  * Return caps we have registered with the MDS(s) as 'wanted'.
  */
@@ -1903,7 +1918,7 @@ retry_locked:
         * If we fail, it's because pages are locked.... try again later.
         */
        if ((!no_delay || mdsc->stopping) &&
-           !S_ISDIR(inode->i_mode) &&          /* ignore readdir cache */
+           S_ISREG(inode->i_mode) &&
            !(ci->i_wb_ref || ci->i_wrbuffer_ref) &&   /* no dirty pages... */
            inode->i_data.nrpages &&            /* have cached pages */
            (revoking & (CEPH_CAP_FILE_CACHE|
@@ -2635,7 +2650,8 @@ again:
                                snap_rwsem_locked = true;
                        }
                        *got = need | (have & want);
-                       if ((need & CEPH_CAP_FILE_RD) &&
+                       if (S_ISREG(inode->i_mode) &&
+                           (need & CEPH_CAP_FILE_RD) &&
                            !(*got & CEPH_CAP_FILE_CACHE))
                                ceph_disable_fscache_readpage(ci);
                        __take_cap_refs(ci, *got, true);
@@ -2643,7 +2659,8 @@ again:
                }
        } else {
                int session_readonly = false;
-               if ((need & CEPH_CAP_FILE_WR) && ci->i_auth_cap) {
+               if (ci->i_auth_cap &&
+                   (need & (CEPH_CAP_FILE_WR | CEPH_CAP_FILE_EXCL))) {
                        struct ceph_mds_session *s = ci->i_auth_cap->session;
                        spin_lock(&s->s_cap_lock);
                        session_readonly = s->s_readonly;
@@ -2817,7 +2834,8 @@ int ceph_get_caps(struct file *filp, int need, int want,
                        return ret;
                }
 
-               if (ci->i_inline_version != CEPH_INLINE_NONE &&
+               if (S_ISREG(ci->vfs_inode.i_mode) &&
+                   ci->i_inline_version != CEPH_INLINE_NONE &&
                    (_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
                    i_size_read(inode) > 0) {
                        struct page *page =
@@ -2850,7 +2868,8 @@ int ceph_get_caps(struct file *filp, int need, int want,
                break;
        }
 
-       if ((_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE))
+       if (S_ISREG(ci->vfs_inode.i_mode) &&
+           (_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE))
                ceph_fscache_revalidate_cookie(ci);
 
        *got = _got;
@@ -3140,7 +3159,7 @@ static void handle_cap_grant(struct inode *inode,
         * try to invalidate (once).  (If there are dirty buffers, we
         * will invalidate _after_ writeback.)
         */
-       if (!S_ISDIR(inode->i_mode) && /* don't invalidate readdir cache */
+       if (S_ISREG(inode->i_mode) && /* don't invalidate readdir cache */
            ((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) &&
            (newcaps & CEPH_CAP_FILE_LAZYIO) == 0 &&
            !(ci->i_wrbuffer_ref || ci->i_wb_ref)) {
@@ -3304,11 +3323,12 @@ static void handle_cap_grant(struct inode *inode,
                     ceph_cap_string(cap->issued),
                     ceph_cap_string(newcaps),
                     ceph_cap_string(revoking));
-               if (revoking & used & CEPH_CAP_FILE_BUFFER)
+               if (S_ISREG(inode->i_mode) &&
+                   (revoking & used & CEPH_CAP_FILE_BUFFER))
                        writeback = true;  /* initiate writeback; will delay ack */
-               else if (revoking == CEPH_CAP_FILE_CACHE &&
-                        (newcaps & CEPH_CAP_FILE_LAZYIO) == 0 &&
-                        queue_invalidate)
+               else if (queue_invalidate &&
+                        revoking == CEPH_CAP_FILE_CACHE &&
+                        (newcaps & CEPH_CAP_FILE_LAZYIO) == 0)
                        ; /* do nothing yet, invalidation will be queued */
                else if (cap == ci->i_auth_cap)
                        check_caps = 1; /* check auth cap only */
index ea52448..2980e57 100644 (file)
@@ -1776,7 +1776,8 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
        }
        /* The inode has cached pages, but it's no longer used.
         * we can safely drop it */
-       if (wanted == 0 && used == CEPH_CAP_FILE_CACHE &&
+       if (S_ISREG(inode->i_mode) &&
+           wanted == 0 && used == CEPH_CAP_FILE_CACHE &&
            !(oissued & CEPH_CAP_FILE_CACHE)) {
          used = 0;
          oissued = 0;
index 2eee34b..37dc1ac 100644 (file)
@@ -675,17 +675,7 @@ extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask);
 extern int __ceph_caps_used(struct ceph_inode_info *ci);
 
 extern int __ceph_caps_file_wanted(struct ceph_inode_info *ci);
-
-/*
- * wanted, by virtue of open file modes AND cap refs (buffered/cached data)
- */
-static inline int __ceph_caps_wanted(struct ceph_inode_info *ci)
-{
-       int w = __ceph_caps_file_wanted(ci) | __ceph_caps_used(ci);
-       if (w & CEPH_CAP_FILE_BUFFER)
-               w |= CEPH_CAP_FILE_EXCL;  /* we want EXCL if dirty data */
-       return w;
-}
+extern int __ceph_caps_wanted(struct ceph_inode_info *ci);
 
 /* what the mds thinks we want */
 extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check);