diff options
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/caps.c | 42 | ||||
-rw-r--r-- | fs/ceph/snap.c | 10 |
2 files changed, 38 insertions, 14 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 7d0a0d0adc18..b6fdf010749b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1204,6 +1204,12 @@ retry: | |||
1204 | if (capsnap->dirty_pages || capsnap->writing) | 1204 | if (capsnap->dirty_pages || capsnap->writing) |
1205 | continue; | 1205 | continue; |
1206 | 1206 | ||
1207 | /* | ||
1208 | * if cap writeback already occurred, we should have dropped | ||
1209 | * the capsnap in ceph_put_wrbuffer_cap_refs. | ||
1210 | */ | ||
1211 | BUG_ON(capsnap->dirty == 0); | ||
1212 | |||
1207 | /* pick mds, take s_mutex */ | 1213 | /* pick mds, take s_mutex */ |
1208 | mds = __ceph_get_cap_mds(ci, &mseq); | 1214 | mds = __ceph_get_cap_mds(ci, &mseq); |
1209 | if (session && session->s_mds != mds) { | 1215 | if (session && session->s_mds != mds) { |
@@ -2117,8 +2123,8 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
2117 | } | 2123 | } |
2118 | spin_unlock(&inode->i_lock); | 2124 | spin_unlock(&inode->i_lock); |
2119 | 2125 | ||
2120 | dout("put_cap_refs %p had %s %s\n", inode, ceph_cap_string(had), | 2126 | dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had), |
2121 | last ? "last" : ""); | 2127 | last ? " last" : "", put ? " put" : ""); |
2122 | 2128 | ||
2123 | if (last && !flushsnaps) | 2129 | if (last && !flushsnaps) |
2124 | ceph_check_caps(ci, 0, NULL); | 2130 | ceph_check_caps(ci, 0, NULL); |
@@ -2142,7 +2148,8 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
2142 | { | 2148 | { |
2143 | struct inode *inode = &ci->vfs_inode; | 2149 | struct inode *inode = &ci->vfs_inode; |
2144 | int last = 0; | 2150 | int last = 0; |
2145 | int last_snap = 0; | 2151 | int complete_capsnap = 0; |
2152 | int drop_capsnap = 0; | ||
2146 | int found = 0; | 2153 | int found = 0; |
2147 | struct ceph_cap_snap *capsnap = NULL; | 2154 | struct ceph_cap_snap *capsnap = NULL; |
2148 | 2155 | ||
@@ -2165,19 +2172,32 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
2165 | list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { | 2172 | list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { |
2166 | if (capsnap->context == snapc) { | 2173 | if (capsnap->context == snapc) { |
2167 | found = 1; | 2174 | found = 1; |
2168 | capsnap->dirty_pages -= nr; | ||
2169 | last_snap = !capsnap->dirty_pages; | ||
2170 | break; | 2175 | break; |
2171 | } | 2176 | } |
2172 | } | 2177 | } |
2173 | BUG_ON(!found); | 2178 | BUG_ON(!found); |
2179 | capsnap->dirty_pages -= nr; | ||
2180 | if (capsnap->dirty_pages == 0) { | ||
2181 | complete_capsnap = 1; | ||
2182 | if (capsnap->dirty == 0) | ||
2183 | /* cap writeback completed before we created | ||
2184 | * the cap_snap; no FLUSHSNAP is needed */ | ||
2185 | drop_capsnap = 1; | ||
2186 | } | ||
2174 | dout("put_wrbuffer_cap_refs on %p cap_snap %p " | 2187 | dout("put_wrbuffer_cap_refs on %p cap_snap %p " |
2175 | " snap %lld %d/%d -> %d/%d %s%s\n", | 2188 | " snap %lld %d/%d -> %d/%d %s%s%s\n", |
2176 | inode, capsnap, capsnap->context->seq, | 2189 | inode, capsnap, capsnap->context->seq, |
2177 | ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr, | 2190 | ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr, |
2178 | ci->i_wrbuffer_ref, capsnap->dirty_pages, | 2191 | ci->i_wrbuffer_ref, capsnap->dirty_pages, |
2179 | last ? " (wrbuffer last)" : "", | 2192 | last ? " (wrbuffer last)" : "", |
2180 | last_snap ? " (capsnap last)" : ""); | 2193 | complete_capsnap ? " (complete capsnap)" : "", |
2194 | drop_capsnap ? " (drop capsnap)" : ""); | ||
2195 | if (drop_capsnap) { | ||
2196 | ceph_put_snap_context(capsnap->context); | ||
2197 | list_del(&capsnap->ci_item); | ||
2198 | list_del(&capsnap->flushing_item); | ||
2199 | ceph_put_cap_snap(capsnap); | ||
2200 | } | ||
2181 | } | 2201 | } |
2182 | 2202 | ||
2183 | spin_unlock(&inode->i_lock); | 2203 | spin_unlock(&inode->i_lock); |
@@ -2185,10 +2205,12 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
2185 | if (last) { | 2205 | if (last) { |
2186 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); | 2206 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); |
2187 | iput(inode); | 2207 | iput(inode); |
2188 | } else if (last_snap) { | 2208 | } else if (complete_capsnap) { |
2189 | ceph_flush_snaps(ci); | 2209 | ceph_flush_snaps(ci); |
2190 | wake_up(&ci->i_cap_wq); | 2210 | wake_up(&ci->i_cap_wq); |
2191 | } | 2211 | } |
2212 | if (drop_capsnap) | ||
2213 | iput(inode); | ||
2192 | } | 2214 | } |
2193 | 2215 | ||
2194 | /* | 2216 | /* |
@@ -2464,8 +2486,8 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, | |||
2464 | break; | 2486 | break; |
2465 | } | 2487 | } |
2466 | WARN_ON(capsnap->dirty_pages || capsnap->writing); | 2488 | WARN_ON(capsnap->dirty_pages || capsnap->writing); |
2467 | dout(" removing cap_snap %p follows %lld\n", | 2489 | dout(" removing %p cap_snap %p follows %lld\n", |
2468 | capsnap, follows); | 2490 | inode, capsnap, follows); |
2469 | ceph_put_snap_context(capsnap->context); | 2491 | ceph_put_snap_context(capsnap->context); |
2470 | list_del(&capsnap->ci_item); | 2492 | list_del(&capsnap->ci_item); |
2471 | list_del(&capsnap->flushing_item); | 2493 | list_del(&capsnap->flushing_item); |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index df04e210a055..7e3e5f9edaa4 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -521,15 +521,17 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci, | |||
521 | capsnap->ctime = inode->i_ctime; | 521 | capsnap->ctime = inode->i_ctime; |
522 | capsnap->time_warp_seq = ci->i_time_warp_seq; | 522 | capsnap->time_warp_seq = ci->i_time_warp_seq; |
523 | if (capsnap->dirty_pages) { | 523 | if (capsnap->dirty_pages) { |
524 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu s=%llu " | 524 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu " |
525 | "still has %d dirty pages\n", inode, capsnap, | 525 | "still has %d dirty pages\n", inode, capsnap, |
526 | capsnap->context, capsnap->context->seq, | 526 | capsnap->context, capsnap->context->seq, |
527 | capsnap->size, capsnap->dirty_pages); | 527 | ceph_cap_string(capsnap->dirty), capsnap->size, |
528 | capsnap->dirty_pages); | ||
528 | return 0; | 529 | return 0; |
529 | } | 530 | } |
530 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu s=%llu clean\n", | 531 | dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu\n", |
531 | inode, capsnap, capsnap->context, | 532 | inode, capsnap, capsnap->context, |
532 | capsnap->context->seq, capsnap->size); | 533 | capsnap->context->seq, ceph_cap_string(capsnap->dirty), |
534 | capsnap->size); | ||
533 | 535 | ||
534 | spin_lock(&mdsc->snap_flush_lock); | 536 | spin_lock(&mdsc->snap_flush_lock); |
535 | list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list); | 537 | list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list); |