diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index b7d218a..3b69f8f 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -199,6 +199,8 @@ static int readpage_nounlock(struct file *filp, struct page *page)
 	u64 off = page_offset(page);
 	u64 len = PAGE_CACHE_SIZE;
 
+	WARN_ON(!PageLocked(page));
+
 	if (off >= i_size_read(inode)) {
 		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
 		SetPageUptodate(page);
@@ -487,6 +489,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
 	int err = 0, len = PAGE_CACHE_SIZE;
 
 	dout("writepage %p idx %lu\n", page, page->index);
+	WARN_ON(!PageLocked(page));
 
 	if (!page->mapping || !page->mapping->host) {
 		dout("writepage %p - no mapping\n", page);
@@ -1055,9 +1058,15 @@ static int ceph_update_writeable_page(struct file *file,
 	int r;
 	struct ceph_snap_context *snapc, *oldest;
 
+	int last_op = 0;
 retry_locked:
 	/* writepages currently holds page lock, but if we change that later, */
+	WARN_ON(PageWriteback(page));
+	if (!PageLocked(page))
+		pr_err("page is unlocked before wait writeback %p, last op %d\n", page, last_op);
 	wait_on_page_writeback(page);
+	if (!PageLocked(page))
+		pr_err("page is unlocked after wait writeback %p last op %d\n", page, last_op);
 
 	snapc = page_snap_context(page);
 	if (snapc && snapc != ci->i_head_snapc) {
@@ -1081,18 +1090,26 @@ retry_locked:
 			r = wait_event_interruptible(ci->i_cap_wq,
 			       context_is_writeable_or_written(inode, snapc));
 			ceph_put_snap_context(snapc);
-			if (r == -ERESTARTSYS)
-				return r;
-			return -EAGAIN;
+			if (r != -ERESTARTSYS)
+				r = -EAGAIN;
+			pr_err("update_writeable_page no snapc %p %d\n", page, r);
+			return r;
 		}
 		ceph_put_snap_context(oldest);
 
 		/* yay, writeable, do it now (without dropping page lock) */
 		dout(" page %p snapc %p not current, but oldest\n",
 		     page, snapc);
-		if (!clear_page_dirty_for_io(page))
+		if (!clear_page_dirty_for_io(page)) {
+			last_op = 1;
+			if (!PageLocked(page))
+				pr_err("clear_page_dirty_for_io unlocks %p\n", page);
 			goto retry_locked;
+		}
 		r = writepage_nounlock(page, NULL);
+		last_op = 2;
+		if (!PageLocked(page))
+			pr_err("writepage_nounlock unlocks %p %d\n", page, r);
 		if (r < 0)
 			goto fail_nosnap;
 		goto retry_locked;
@@ -1123,11 +1140,15 @@ retry_locked:
 
 	/* we need to read it. */
 	r = readpage_nounlock(file, page);
+	last_op = 3;
+	if (!PageLocked(page))
+		pr_err("readpage_nounlock unlocks %p %d\n", page, r);
 	if (r < 0)
 		goto fail_nosnap;
 	goto retry_locked;
 fail_nosnap:
 	unlock_page(page);
+	pr_err("update_writeable_page failed %p %d\n", page, r);
 	return r;
 }
 
@@ -1149,16 +1170,19 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
 		page = grab_cache_page_write_begin(mapping, index, 0);
 		if (!page)
 			return -ENOMEM;
+		WARN_ON(!PageLocked(page));
 		*pagep = page;
 
 		dout("write_begin file %p inode %p page %p %d~%d\n", file,
 		     inode, page, (int)pos, (int)len);
 
 		r = ceph_update_writeable_page(file, pos, len, page);
-		if (r < 0)
+		if (r < 0) {
 			page_cache_release(page);
-		else
+		} else {
+			WARN_ON(!PageLocked(page));
 			*pagep = page;
+		}
 	} while (r == -EAGAIN);
 
 	return r;
@@ -1378,11 +1402,13 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 	ret = VM_FAULT_NOPAGE;
 	if ((off > size) ||
-	    (page->mapping != inode->i_mapping))
+	    (page->mapping != inode->i_mapping)) {
+		unlock_page(page);
 		goto out;
+	}
 
 	ret = ceph_update_writeable_page(vma->vm_file, off, len, page);
-	if (ret == 0) {
+	if (ret >= 0) {
 		/* success.  we'll keep the page locked. */
 		set_page_dirty(page);
 		ret = VM_FAULT_LOCKED;
@@ -1393,8 +1419,6 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 			ret = VM_FAULT_SIGBUS;
 	}
 out:
-	if (ret != VM_FAULT_LOCKED)
-		unlock_page(page);
 	if (ret == VM_FAULT_LOCKED ||
 	    ci->i_inline_version != CEPH_INLINE_NONE) {
 		int dirty;
