Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ceph: record truncate size/seq for snap data writeback

Dirty snapshot data needs to be flushed unconditionally. If they
were created before truncation, writeback should use old truncate
size/seq.

Signed-off-by: Yan, Zheng <zyan@redhat.com>

authored by

Yan, Zheng and committed by
Ilya Dryomov
5f743e45 e9e427f0

+22 -13
+18 -13
fs/ceph/addr.c
··· 474 474 * only snap context we are allowed to write back. 475 475 */ 476 476 static struct ceph_snap_context *get_oldest_context(struct inode *inode, 477 - loff_t *snap_size) 477 + loff_t *snap_size, 478 + u64 *truncate_size, 479 + u32 *truncate_seq) 478 480 { 479 481 struct ceph_inode_info *ci = ceph_inode(inode); 480 482 struct ceph_snap_context *snapc = NULL; ··· 490 488 snapc = ceph_get_snap_context(capsnap->context); 491 489 if (snap_size) 492 490 *snap_size = capsnap->size; 491 + if (truncate_size) 492 + *truncate_size = capsnap->truncate_size; 493 + if (truncate_seq) 494 + *truncate_seq = capsnap->truncate_seq; 493 495 break; 494 496 } 495 497 } ··· 501 495 snapc = ceph_get_snap_context(ci->i_head_snapc); 502 496 dout(" head snapc %p has %d dirty pages\n", 503 497 snapc, ci->i_wrbuffer_ref_head); 498 + if (truncate_size) 499 + *truncate_size = capsnap->truncate_size; 500 + if (truncate_seq) 501 + *truncate_seq = capsnap->truncate_seq; 504 502 } 505 503 spin_unlock(&ci->i_ceph_lock); 506 504 return snapc; ··· 547 537 dout("writepage %p page %p not dirty?\n", inode, page); 548 538 goto out; 549 539 } 550 - oldest = get_oldest_context(inode, &snap_size); 540 + oldest = get_oldest_context(inode, &snap_size, 541 + &truncate_size, &truncate_seq); 551 542 if (snapc->seq > oldest->seq) { 552 543 dout("writepage %p page %p snapc %p not writeable - noop\n", 553 544 inode, page, snapc); ··· 559 548 } 560 549 ceph_put_snap_context(oldest); 561 550 562 - spin_lock(&ci->i_ceph_lock); 563 - truncate_seq = ci->i_truncate_seq; 564 - truncate_size = ci->i_truncate_size; 565 551 if (snap_size == -1) 566 552 snap_size = i_size_read(inode); 567 - spin_unlock(&ci->i_ceph_lock); 568 553 569 554 /* is this a partial page at end of file? */ 570 555 if (page_off >= snap_size) { ··· 807 800 /* find oldest snap context with dirty data */ 808 801 ceph_put_snap_context(snapc); 809 802 snap_size = -1; 810 - snapc = get_oldest_context(inode, &snap_size); 803 + snapc = get_oldest_context(inode, &snap_size, 804 + &truncate_size, &truncate_seq); 811 805 if (!snapc) { 812 806 /* hmm, why does writepages get called when there 813 807 is no dirty data? */ ··· 818 810 dout(" oldest snapc is %p seq %lld (%d snaps)\n", 819 811 snapc, snapc->seq, snapc->num_snaps); 820 812 821 - spin_lock(&ci->i_ceph_lock); 822 - truncate_seq = ci->i_truncate_seq; 823 - truncate_size = ci->i_truncate_size; 824 813 i_size = i_size_read(inode); 825 - spin_unlock(&ci->i_ceph_lock); 826 814 827 815 if (last_snapc && snapc != last_snapc) { 828 816 /* if we switched to a newer snapc, restart our scan at the ··· 1164 1160 static int context_is_writeable_or_written(struct inode *inode, 1165 1161 struct ceph_snap_context *snapc) 1166 1162 { 1167 - struct ceph_snap_context *oldest = get_oldest_context(inode, NULL); 1163 + struct ceph_snap_context *oldest = get_oldest_context(inode, NULL, 1164 + NULL, NULL); 1168 1165 int ret = !oldest || snapc->seq <= oldest->seq; 1169 1166 1170 1167 ceph_put_snap_context(oldest); ··· 1210 1205 * this page is already dirty in another (older) snap 1211 1206 * context! is it writeable now? 1212 1207 */ 1213 - oldest = get_oldest_context(inode, NULL); 1208 + oldest = get_oldest_context(inode, NULL, NULL, NULL); 1214 1209 1215 1210 if (snapc->seq > oldest->seq) { 1216 1211 ceph_put_snap_context(oldest);
+2
fs/ceph/snap.c
··· 593 593 capsnap->atime = inode->i_atime; 594 594 capsnap->ctime = inode->i_ctime; 595 595 capsnap->time_warp_seq = ci->i_time_warp_seq; 596 + capsnap->truncate_size = ci->i_truncate_size; 597 + capsnap->truncate_seq = ci->i_truncate_seq; 596 598 if (capsnap->dirty_pages) { 597 599 dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu " 598 600 "still has %d dirty pages\n", inode, capsnap,
+2
fs/ceph/super.h
··· 181 181 u64 size; 182 182 struct timespec mtime, atime, ctime; 183 183 u64 time_warp_seq; 184 + u64 truncate_size; 185 + u32 truncate_seq; 184 186 int writing; /* a sync write is still in progress */ 185 187 int dirty_pages; /* dirty pages awaiting writeback */ 186 188 bool inline_data;