aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-08-05 02:10:29 -0400
committerSage Weil <sage@inktank.com>2013-08-15 14:12:11 -0400
commit3871cbb9a41b1371dc13fc619e3ab4e0a1e29b4a (patch)
tree527e72ea247c0bc632a28f021aa4b8149ecf78e8 /fs/ceph/caps.c
parentb0d7c2231015b331b942746610a05b6ea72977ab (diff)
ceph: fix request max size
ceph_check_caps() requests new max size only when there is Fw cap. If we call check_max_size() while there is no Fw cap. It updates i_wanted_max_size and calls ceph_check_caps(), but ceph_check_caps() does nothing. Later when Fw cap is issued, we call check_max_size() again. But i_wanted_max_size is equal to 'endoff' at this time, so check_max_size() doesn't call ceph_check_caps() and we end up with waiting for the new max size forever. The fix is duplicate ceph_check_caps()'s "request max size" code in check_max_size(), and make try_get_cap_refs() wait for the Fw cap before retry requesting new max size. This patch also removes the "endoff > (inode->i_size << 1)" check in check_max_size(). It's useless because there is no corresponding logic in ceph_check_caps(). Reviewed-by: Sage Weil <sage@inktank.com> Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 0e94d27fa284..165ebbeab1c3 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2076,11 +2076,13 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
2076 spin_lock(&ci->i_ceph_lock); 2076 spin_lock(&ci->i_ceph_lock);
2077 } 2077 }
2078 2078
2079 if (need & CEPH_CAP_FILE_WR) { 2079 have = __ceph_caps_issued(ci, &implemented);
2080
2081 if (have & need & CEPH_CAP_FILE_WR) {
2080 if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) { 2082 if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) {
2081 dout("get_cap_refs %p endoff %llu > maxsize %llu\n", 2083 dout("get_cap_refs %p endoff %llu > maxsize %llu\n",
2082 inode, endoff, ci->i_max_size); 2084 inode, endoff, ci->i_max_size);
2083 if (endoff > ci->i_wanted_max_size) { 2085 if (endoff > ci->i_requested_max_size) {
2084 *check_max = 1; 2086 *check_max = 1;
2085 ret = 1; 2087 ret = 1;
2086 } 2088 }
@@ -2095,7 +2097,6 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
2095 goto out; 2097 goto out;
2096 } 2098 }
2097 } 2099 }
2098 have = __ceph_caps_issued(ci, &implemented);
2099 2100
2100 if ((have & need) == need) { 2101 if ((have & need) == need) {
2101 /* 2102 /*
@@ -2137,14 +2138,17 @@ static void check_max_size(struct inode *inode, loff_t endoff)
2137 2138
2138 /* do we need to explicitly request a larger max_size? */ 2139 /* do we need to explicitly request a larger max_size? */
2139 spin_lock(&ci->i_ceph_lock); 2140 spin_lock(&ci->i_ceph_lock);
2140 if ((endoff >= ci->i_max_size || 2141 if (endoff >= ci->i_max_size && endoff > ci->i_wanted_max_size) {
2141 endoff > (inode->i_size << 1)) &&
2142 endoff > ci->i_wanted_max_size) {
2143 dout("write %p at large endoff %llu, req max_size\n", 2142 dout("write %p at large endoff %llu, req max_size\n",
2144 inode, endoff); 2143 inode, endoff);
2145 ci->i_wanted_max_size = endoff; 2144 ci->i_wanted_max_size = endoff;
2146 check = 1;
2147 } 2145 }
2146 /* duplicate ceph_check_caps()'s logic */
2147 if (ci->i_auth_cap &&
2148 (ci->i_auth_cap->issued & CEPH_CAP_FILE_WR) &&
2149 ci->i_wanted_max_size > ci->i_max_size &&
2150 ci->i_wanted_max_size > ci->i_requested_max_size)
2151 check = 1;
2148 spin_unlock(&ci->i_ceph_lock); 2152 spin_unlock(&ci->i_ceph_lock);
2149 if (check) 2153 if (check)
2150 ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); 2154 ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);