]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/ceph/caps.c
Merge tag 'kvm-4.13-2' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[karo-tx-linux.git] / fs / ceph / caps.c
index a3ebb632294e7b90a315508c9b75671d2ce8ff6a..7007ae2a5ad2ec4e506ca8216c2fd5253ee35bca 100644 (file)
@@ -1653,6 +1653,21 @@ static int try_nonblocking_invalidate(struct inode *inode)
        return -1;
 }
 
+bool __ceph_should_report_size(struct ceph_inode_info *ci)
+{
+       loff_t size = ci->vfs_inode.i_size;
+       /* mds will adjust max size according to the reported size */
+       if (ci->i_flushing_caps & CEPH_CAP_FILE_WR)
+               return false;
+       if (size >= ci->i_max_size)
+               return true;
+       /* half of previous max_size increment has been used */
+       if (ci->i_max_size > ci->i_reported_size &&
+           (size << 1) >= ci->i_max_size + ci->i_reported_size)
+               return true;
+       return false;
+}
+
 /*
  * Swiss army knife function to examine currently used and wanted
  * versus held caps.  Release, flush, ack revoked caps to mds as
@@ -1806,8 +1821,7 @@ retry_locked:
                        }
 
                        /* approaching file_max? */
-                       if ((inode->i_size << 1) >= ci->i_max_size &&
-                           (ci->i_reported_size << 1) < ci->i_max_size) {
+                       if (__ceph_should_report_size(ci)) {
                                dout("i_size approaching max_size\n");
                                goto ack;
                        }
@@ -3027,8 +3041,10 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
                                        le32_to_cpu(grant->truncate_seq),
                                        le64_to_cpu(grant->truncate_size),
                                        size);
-               /* max size increase? */
-               if (ci->i_auth_cap == cap && max_size != ci->i_max_size) {
+       }
+
+       if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) {
+               if (max_size != ci->i_max_size) {
                        dout("max_size %lld -> %llu\n",
                             ci->i_max_size, max_size);
                        ci->i_max_size = max_size;
@@ -3037,6 +3053,10 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
                                ci->i_requested_max_size = 0;
                        }
                        wake = true;
+               } else if (ci->i_wanted_max_size > ci->i_max_size &&
+                          ci->i_wanted_max_size > ci->i_requested_max_size) {
+                       /* CEPH_CAP_OP_IMPORT */
+                       wake = true;
                }
        }
 
@@ -3554,7 +3574,6 @@ retry:
        }
 
        /* make sure we re-request max_size, if necessary */
-       ci->i_wanted_max_size = 0;
        ci->i_requested_max_size = 0;
 
        *old_issued = issued;
@@ -3790,6 +3809,7 @@ bad:
  */
 void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
 {
+       struct inode *inode;
        struct ceph_inode_info *ci;
        int flags = CHECK_CAPS_NODELAY;
 
@@ -3805,9 +3825,15 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
                    time_before(jiffies, ci->i_hold_caps_max))
                        break;
                list_del_init(&ci->i_cap_delay_list);
+
+               inode = igrab(&ci->vfs_inode);
                spin_unlock(&mdsc->cap_delay_lock);
-               dout("check_delayed_caps on %p\n", &ci->vfs_inode);
-               ceph_check_caps(ci, flags, NULL);
+
+               if (inode) {
+                       dout("check_delayed_caps on %p\n", inode);
+                       ceph_check_caps(ci, flags, NULL);
+                       iput(inode);
+               }
        }
        spin_unlock(&mdsc->cap_delay_lock);
 }