@@ -476,7 +476,8 @@ struct ceph_writeback_ctl
476476 * only snap context we are allowed to write back.
477477 */
478478static struct ceph_snap_context *
479- get_oldest_context (struct inode * inode , struct ceph_writeback_ctl * ctl )
479+ get_oldest_context (struct inode * inode , struct ceph_writeback_ctl * ctl ,
480+ struct ceph_snap_context * page_snapc )
480481{
481482 struct ceph_inode_info * ci = ceph_inode (inode );
482483 struct ceph_snap_context * snapc = NULL ;
@@ -486,21 +487,33 @@ get_oldest_context(struct inode *inode, struct ceph_writeback_ctl *ctl)
486487 list_for_each_entry (capsnap , & ci -> i_cap_snaps , ci_item ) {
487488 dout (" cap_snap %p snapc %p has %d dirty pages\n" , capsnap ,
488489 capsnap -> context , capsnap -> dirty_pages );
489- if (capsnap -> dirty_pages ) {
490- snapc = ceph_get_snap_context (capsnap -> context );
491- if (ctl ) {
492- if (capsnap -> writing ) {
493- ctl -> i_size = i_size_read (inode );
494- ctl -> size_stable = false;
495- } else {
496- ctl -> i_size = capsnap -> size ;
497- ctl -> size_stable = true;
498- }
499- ctl -> truncate_size = capsnap -> truncate_size ;
500- ctl -> truncate_seq = capsnap -> truncate_seq ;
490+ if (!capsnap -> dirty_pages )
491+ continue ;
492+
493+ /* get i_size, truncate_{seq,size} for page_snapc? */
494+ if (snapc && capsnap -> context != page_snapc )
495+ continue ;
496+
497+ if (ctl ) {
498+ if (capsnap -> writing ) {
499+ ctl -> i_size = i_size_read (inode );
500+ ctl -> size_stable = false;
501+ } else {
502+ ctl -> i_size = capsnap -> size ;
503+ ctl -> size_stable = true;
501504 }
502- break ;
505+ ctl -> truncate_size = capsnap -> truncate_size ;
506+ ctl -> truncate_seq = capsnap -> truncate_seq ;
503507 }
508+
509+ if (snapc )
510+ break ;
511+
512+ snapc = ceph_get_snap_context (capsnap -> context );
513+ if (!page_snapc ||
514+ page_snapc == snapc ||
515+ page_snapc -> seq > snapc -> seq )
516+ break ;
504517 }
505518 if (!snapc && ci -> i_wrbuffer_ref_head ) {
506519 snapc = ceph_get_snap_context (ci -> i_head_snapc );
@@ -573,7 +586,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
573586 dout ("writepage %p page %p not dirty?\n" , inode , page );
574587 return 0 ;
575588 }
576- oldest = get_oldest_context (inode , & ceph_wbc );
589+ oldest = get_oldest_context (inode , & ceph_wbc , snapc );
577590 if (snapc -> seq > oldest -> seq ) {
578591 dout ("writepage %p page %p snapc %p not writeable - noop\n" ,
579592 inode , page , snapc );
@@ -588,6 +601,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
588601 /* is this a partial page at end of file? */
589602 if (page_off >= ceph_wbc .i_size ) {
590603 dout ("%p page eof %llu\n" , page , ceph_wbc .i_size );
604+ page -> mapping -> a_ops -> invalidatepage (page , 0 , PAGE_SIZE );
591605 return 0 ;
592606 }
593607
@@ -816,7 +830,7 @@ static int ceph_writepages_start(struct address_space *mapping,
816830retry :
817831 /* find oldest snap context with dirty data */
818832 ceph_put_snap_context (snapc );
819- snapc = get_oldest_context (inode , & ceph_wbc );
833+ snapc = get_oldest_context (inode , & ceph_wbc , NULL );
820834 if (!snapc ) {
821835 /* hmm, why does writepages get called when there
822836 is no dirty data? */
@@ -1162,7 +1176,7 @@ static int ceph_writepages_start(struct address_space *mapping,
11621176static int context_is_writeable_or_written (struct inode * inode ,
11631177 struct ceph_snap_context * snapc )
11641178{
1165- struct ceph_snap_context * oldest = get_oldest_context (inode , NULL );
1179+ struct ceph_snap_context * oldest = get_oldest_context (inode , NULL , NULL );
11661180 int ret = !oldest || snapc -> seq <= oldest -> seq ;
11671181
11681182 ceph_put_snap_context (oldest );
@@ -1207,7 +1221,7 @@ static int ceph_update_writeable_page(struct file *file,
12071221 * this page is already dirty in another (older) snap
12081222 * context! is it writeable now?
12091223 */
1210- oldest = get_oldest_context (inode , NULL );
1224+ oldest = get_oldest_context (inode , NULL , NULL );
12111225 if (snapc -> seq > oldest -> seq ) {
12121226 ceph_put_snap_context (oldest );
12131227 dout (" page %p snapc %p not current or oldest\n" ,
0 commit comments