aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/addr.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index ce8ef6107727..a313e9baeed0 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -356,8 +356,8 @@ static struct ceph_snap_context *__get_oldest_context(struct inode *inode,
356 break; 356 break;
357 } 357 }
358 } 358 }
359 if (!snapc && ci->i_snap_realm) { 359 if (!snapc && ci->i_head_snapc) {
360 snapc = ceph_get_snap_context(ci->i_snap_realm->cached_context); 360 snapc = ceph_get_snap_context(ci->i_head_snapc);
361 dout(" head snapc %p has %d dirty pages\n", 361 dout(" head snapc %p has %d dirty pages\n",
362 snapc, ci->i_wrbuffer_ref_head); 362 snapc, ci->i_wrbuffer_ref_head);
363 } 363 }
@@ -412,7 +412,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
412 dout("writepage %p page %p not dirty?\n", inode, page); 412 dout("writepage %p page %p not dirty?\n", inode, page);
413 goto out; 413 goto out;
414 } 414 }
415 if (snapc != get_oldest_context(inode, &snap_size)) { 415 if (snapc->seq > get_oldest_context(inode, &snap_size)->seq) {
416 dout("writepage %p page %p snapc %p not writeable - noop\n", 416 dout("writepage %p page %p snapc %p not writeable - noop\n",
417 inode, page, (void *)page->private); 417 inode, page, (void *)page->private);
418 /* we should only noop if called by kswapd */ 418 /* we should only noop if called by kswapd */
@@ -557,9 +557,9 @@ static void writepages_finish(struct ceph_osd_request *req,
557 dout("inode %p skipping page %p\n", inode, page); 557 dout("inode %p skipping page %p\n", inode, page);
558 wbc->pages_skipped++; 558 wbc->pages_skipped++;
559 } 559 }
560 ceph_put_snap_context((void *)page->private);
560 page->private = 0; 561 page->private = 0;
561 ClearPagePrivate(page); 562 ClearPagePrivate(page);
562 ceph_put_snap_context(snapc);
563 dout("unlocking %d %p\n", i, page); 563 dout("unlocking %d %p\n", i, page);
564 end_page_writeback(page); 564 end_page_writeback(page);
565 565
@@ -617,7 +617,7 @@ static int ceph_writepages_start(struct address_space *mapping,
617 int range_whole = 0; 617 int range_whole = 0;
618 int should_loop = 1; 618 int should_loop = 1;
619 pgoff_t max_pages = 0, max_pages_ever = 0; 619 pgoff_t max_pages = 0, max_pages_ever = 0;
620 struct ceph_snap_context *snapc = NULL, *last_snapc = NULL; 620 struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc;
621 struct pagevec pvec; 621 struct pagevec pvec;
622 int done = 0; 622 int done = 0;
623 int rc = 0; 623 int rc = 0;
@@ -769,9 +769,10 @@ get_more_pages:
769 } 769 }
770 770
771 /* only if matching snap context */ 771 /* only if matching snap context */
772 if (snapc != (void *)page->private) { 772 pgsnapc = (void *)page->private;
773 dout("page snapc %p != oldest %p\n", 773 if (pgsnapc->seq > snapc->seq) {
774 (void *)page->private, snapc); 774 dout("page snapc %p %lld > oldest %p %lld\n",
775 pgsnapc, pgsnapc->seq, snapc, snapc->seq);
775 unlock_page(page); 776 unlock_page(page);
776 if (!locked_pages) 777 if (!locked_pages)
777 continue; /* keep looking for snap */ 778 continue; /* keep looking for snap */
@@ -935,8 +936,8 @@ static int ceph_update_writeable_page(struct file *file,
935 int pos_in_page = pos & ~PAGE_CACHE_MASK; 936 int pos_in_page = pos & ~PAGE_CACHE_MASK;
936 int end_in_page = pos_in_page + len; 937 int end_in_page = pos_in_page + len;
937 loff_t i_size; 938 loff_t i_size;
938 struct ceph_snap_context *snapc;
939 int r; 939 int r;
940 struct ceph_snap_context *snapc, *oldest;
940 941
941retry_locked: 942retry_locked:
942 /* writepages currently holds page lock, but if we change that later, */ 943 /* writepages currently holds page lock, but if we change that later, */
@@ -946,16 +947,16 @@ retry_locked:
946 BUG_ON(!ci->i_snap_realm); 947 BUG_ON(!ci->i_snap_realm);
947 down_read(&mdsc->snap_rwsem); 948 down_read(&mdsc->snap_rwsem);
948 BUG_ON(!ci->i_snap_realm->cached_context); 949 BUG_ON(!ci->i_snap_realm->cached_context);
949 if (page->private && 950 snapc = (void *)page->private;
950 (void *)page->private != ci->i_snap_realm->cached_context) { 951 if (snapc && snapc != ci->i_head_snapc) {
951 /* 952 /*
952 * this page is already dirty in another (older) snap 953 * this page is already dirty in another (older) snap
953 * context! is it writeable now? 954 * context! is it writeable now?
954 */ 955 */
955 snapc = get_oldest_context(inode, NULL); 956 oldest = get_oldest_context(inode, NULL);
956 up_read(&mdsc->snap_rwsem); 957 up_read(&mdsc->snap_rwsem);
957 958
958 if (snapc != (void *)page->private) { 959 if (snapc->seq > oldest->seq) {
959 dout(" page %p snapc %p not current or oldest\n", 960 dout(" page %p snapc %p not current or oldest\n",
960 page, (void *)page->private); 961 page, (void *)page->private);
961 /* 962 /*