diff options
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index a2069b6680ae..5e9da996a151 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -814,7 +814,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci) | |||
814 | used |= CEPH_CAP_PIN; | 814 | used |= CEPH_CAP_PIN; |
815 | if (ci->i_rd_ref) | 815 | if (ci->i_rd_ref) |
816 | used |= CEPH_CAP_FILE_RD; | 816 | used |= CEPH_CAP_FILE_RD; |
817 | if (ci->i_rdcache_ref || ci->i_rdcache_gen) | 817 | if (ci->i_rdcache_ref || ci->vfs_inode.i_data.nrpages) |
818 | used |= CEPH_CAP_FILE_CACHE; | 818 | used |= CEPH_CAP_FILE_CACHE; |
819 | if (ci->i_wr_ref) | 819 | if (ci->i_wr_ref) |
820 | used |= CEPH_CAP_FILE_WR; | 820 | used |= CEPH_CAP_FILE_WR; |
@@ -1195,10 +1195,14 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, | |||
1195 | * asynchronously back to the MDS once sync writes complete and dirty | 1195 | * asynchronously back to the MDS once sync writes complete and dirty |
1196 | * data is written out. | 1196 | * data is written out. |
1197 | * | 1197 | * |
1198 | * Unless @again is true, skip cap_snaps that were already sent to | ||
1199 | * the MDS (i.e., during this session). | ||
1200 | * | ||
1198 | * Called under i_lock. Takes s_mutex as needed. | 1201 | * Called under i_lock. Takes s_mutex as needed. |
1199 | */ | 1202 | */ |
1200 | void __ceph_flush_snaps(struct ceph_inode_info *ci, | 1203 | void __ceph_flush_snaps(struct ceph_inode_info *ci, |
1201 | struct ceph_mds_session **psession) | 1204 | struct ceph_mds_session **psession, |
1205 | int again) | ||
1202 | __releases(ci->vfs_inode->i_lock) | 1206 | __releases(ci->vfs_inode->i_lock) |
1203 | __acquires(ci->vfs_inode->i_lock) | 1207 | __acquires(ci->vfs_inode->i_lock) |
1204 | { | 1208 | { |
@@ -1227,7 +1231,7 @@ retry: | |||
1227 | * pages to be written out. | 1231 | * pages to be written out. |
1228 | */ | 1232 | */ |
1229 | if (capsnap->dirty_pages || capsnap->writing) | 1233 | if (capsnap->dirty_pages || capsnap->writing) |
1230 | continue; | 1234 | break; |
1231 | 1235 | ||
1232 | /* | 1236 | /* |
1233 | * if cap writeback already occurred, we should have dropped | 1237 | * if cap writeback already occurred, we should have dropped |
@@ -1240,6 +1244,13 @@ retry: | |||
1240 | dout("no auth cap (migrating?), doing nothing\n"); | 1244 | dout("no auth cap (migrating?), doing nothing\n"); |
1241 | goto out; | 1245 | goto out; |
1242 | } | 1246 | } |
1247 | |||
1248 | /* only flush each capsnap once */ | ||
1249 | if (!again && !list_empty(&capsnap->flushing_item)) { | ||
1250 | dout("already flushed %p, skipping\n", capsnap); | ||
1251 | continue; | ||
1252 | } | ||
1253 | |||
1243 | mds = ci->i_auth_cap->session->s_mds; | 1254 | mds = ci->i_auth_cap->session->s_mds; |
1244 | mseq = ci->i_auth_cap->mseq; | 1255 | mseq = ci->i_auth_cap->mseq; |
1245 | 1256 | ||
@@ -1276,8 +1287,8 @@ retry: | |||
1276 | &session->s_cap_snaps_flushing); | 1287 | &session->s_cap_snaps_flushing); |
1277 | spin_unlock(&inode->i_lock); | 1288 | spin_unlock(&inode->i_lock); |
1278 | 1289 | ||
1279 | dout("flush_snaps %p cap_snap %p follows %lld size %llu\n", | 1290 | dout("flush_snaps %p cap_snap %p follows %lld tid %llu\n", |
1280 | inode, capsnap, next_follows, capsnap->size); | 1291 | inode, capsnap, capsnap->follows, capsnap->flush_tid); |
1281 | send_cap_msg(session, ceph_vino(inode).ino, 0, | 1292 | send_cap_msg(session, ceph_vino(inode).ino, 0, |
1282 | CEPH_CAP_OP_FLUSHSNAP, capsnap->issued, 0, | 1293 | CEPH_CAP_OP_FLUSHSNAP, capsnap->issued, 0, |
1283 | capsnap->dirty, 0, capsnap->flush_tid, 0, mseq, | 1294 | capsnap->dirty, 0, capsnap->flush_tid, 0, mseq, |
@@ -1314,7 +1325,7 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) | |||
1314 | struct inode *inode = &ci->vfs_inode; | 1325 | struct inode *inode = &ci->vfs_inode; |
1315 | 1326 | ||
1316 | spin_lock(&inode->i_lock); | 1327 | spin_lock(&inode->i_lock); |
1317 | __ceph_flush_snaps(ci, NULL); | 1328 | __ceph_flush_snaps(ci, NULL, 0); |
1318 | spin_unlock(&inode->i_lock); | 1329 | spin_unlock(&inode->i_lock); |
1319 | } | 1330 | } |
1320 | 1331 | ||
@@ -1477,7 +1488,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, | |||
1477 | 1488 | ||
1478 | /* flush snaps first time around only */ | 1489 | /* flush snaps first time around only */ |
1479 | if (!list_empty(&ci->i_cap_snaps)) | 1490 | if (!list_empty(&ci->i_cap_snaps)) |
1480 | __ceph_flush_snaps(ci, &session); | 1491 | __ceph_flush_snaps(ci, &session, 0); |
1481 | goto retry_locked; | 1492 | goto retry_locked; |
1482 | retry: | 1493 | retry: |
1483 | spin_lock(&inode->i_lock); | 1494 | spin_lock(&inode->i_lock); |
@@ -1894,7 +1905,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, | |||
1894 | if (cap && cap->session == session) { | 1905 | if (cap && cap->session == session) { |
1895 | dout("kick_flushing_caps %p cap %p capsnap %p\n", inode, | 1906 | dout("kick_flushing_caps %p cap %p capsnap %p\n", inode, |
1896 | cap, capsnap); | 1907 | cap, capsnap); |
1897 | __ceph_flush_snaps(ci, &session); | 1908 | __ceph_flush_snaps(ci, &session, 1); |
1898 | } else { | 1909 | } else { |
1899 | pr_err("%p auth cap %p not mds%d ???\n", inode, | 1910 | pr_err("%p auth cap %p not mds%d ???\n", inode, |
1900 | cap, session->s_mds); | 1911 | cap, session->s_mds); |
@@ -2272,7 +2283,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2272 | { | 2283 | { |
2273 | struct ceph_inode_info *ci = ceph_inode(inode); | 2284 | struct ceph_inode_info *ci = ceph_inode(inode); |
2274 | int mds = session->s_mds; | 2285 | int mds = session->s_mds; |
2275 | int seq = le32_to_cpu(grant->seq); | 2286 | unsigned seq = le32_to_cpu(grant->seq); |
2287 | unsigned issue_seq = le32_to_cpu(grant->issue_seq); | ||
2276 | int newcaps = le32_to_cpu(grant->caps); | 2288 | int newcaps = le32_to_cpu(grant->caps); |
2277 | int issued, implemented, used, wanted, dirty; | 2289 | int issued, implemented, used, wanted, dirty; |
2278 | u64 size = le64_to_cpu(grant->size); | 2290 | u64 size = le64_to_cpu(grant->size); |
@@ -2284,8 +2296,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2284 | int revoked_rdcache = 0; | 2296 | int revoked_rdcache = 0; |
2285 | int queue_invalidate = 0; | 2297 | int queue_invalidate = 0; |
2286 | 2298 | ||
2287 | dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", | 2299 | dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n", |
2288 | inode, cap, mds, seq, ceph_cap_string(newcaps)); | 2300 | inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps)); |
2289 | dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, | 2301 | dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, |
2290 | inode->i_size); | 2302 | inode->i_size); |
2291 | 2303 | ||
@@ -2381,6 +2393,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2381 | } | 2393 | } |
2382 | 2394 | ||
2383 | cap->seq = seq; | 2395 | cap->seq = seq; |
2396 | cap->issue_seq = issue_seq; | ||
2384 | 2397 | ||
2385 | /* file layout may have changed */ | 2398 | /* file layout may have changed */ |
2386 | ci->i_layout = grant->layout; | 2399 | ci->i_layout = grant->layout; |
@@ -2763,15 +2776,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2763 | if (op == CEPH_CAP_OP_IMPORT) | 2776 | if (op == CEPH_CAP_OP_IMPORT) |
2764 | __queue_cap_release(session, vino.ino, cap_id, | 2777 | __queue_cap_release(session, vino.ino, cap_id, |
2765 | mseq, seq); | 2778 | mseq, seq); |
2766 | 2779 | goto flush_cap_releases; | |
2767 | /* | ||
2768 | * send any full release message to try to move things | ||
2769 | * along for the mds (who clearly thinks we still have this | ||
2770 | * cap). | ||
2771 | */ | ||
2772 | ceph_add_cap_releases(mdsc, session); | ||
2773 | ceph_send_cap_releases(mdsc, session); | ||
2774 | goto done; | ||
2775 | } | 2780 | } |
2776 | 2781 | ||
2777 | /* these will work even if we don't have a cap yet */ | 2782 | /* these will work even if we don't have a cap yet */ |
@@ -2799,7 +2804,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2799 | dout(" no cap on %p ino %llx.%llx from mds%d\n", | 2804 | dout(" no cap on %p ino %llx.%llx from mds%d\n", |
2800 | inode, ceph_ino(inode), ceph_snap(inode), mds); | 2805 | inode, ceph_ino(inode), ceph_snap(inode), mds); |
2801 | spin_unlock(&inode->i_lock); | 2806 | spin_unlock(&inode->i_lock); |
2802 | goto done; | 2807 | goto flush_cap_releases; |
2803 | } | 2808 | } |
2804 | 2809 | ||
2805 | /* note that each of these drops i_lock for us */ | 2810 | /* note that each of these drops i_lock for us */ |
@@ -2823,6 +2828,17 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2823 | ceph_cap_op_name(op)); | 2828 | ceph_cap_op_name(op)); |
2824 | } | 2829 | } |
2825 | 2830 | ||
2831 | goto done; | ||
2832 | |||
2833 | flush_cap_releases: | ||
2834 | /* | ||
2835 | * send any full release message to try to move things | ||
2836 | * along for the mds (who clearly thinks we still have this | ||
2837 | * cap). | ||
2838 | */ | ||
2839 | ceph_add_cap_releases(mdsc, session); | ||
2840 | ceph_send_cap_releases(mdsc, session); | ||
2841 | |||
2826 | done: | 2842 | done: |
2827 | mutex_unlock(&session->s_mutex); | 2843 | mutex_unlock(&session->s_mutex); |
2828 | done_unlocked: | 2844 | done_unlocked: |