diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/addr.c | 27 |
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 | ||
941 | retry_locked: | 942 | retry_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 | /* |