ceph: remove page upon writeback completion if lost cache cap
authorYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 19 Feb 2010 00:07:01 +0000 (00:07 +0000)
committerSage Weil <sage@newdream.net>
Fri, 19 Feb 2010 22:34:18 +0000 (14:34 -0800)
This page should have been removed earlier when the cache cap was
revoked, but a writeback was in flight, so it was skipped. We truncate
it here just as the writeback finishes, while it's still locked.

Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
fs/ceph/addr.c

index 71f5ad1c1e267d2749555a86b23f80b40c1df0fd..25360d517d1be0f8e4927372f96712ae8561ae4f 100644 (file)
@@ -514,6 +514,7 @@ static void writepages_finish(struct ceph_osd_request *req,
        u64 bytes = 0;
        struct ceph_client *client = ceph_inode_to_client(inode);
        long writeback_stat;
+       unsigned issued = __ceph_caps_issued(ci, NULL);
 
        /* parse reply */
        replyhead = msg->front.iov_base;
@@ -559,6 +560,16 @@ static void writepages_finish(struct ceph_osd_request *req,
                ceph_put_snap_context(snapc);
                dout("unlocking %d %p\n", i, page);
                end_page_writeback(page);
+
+               /*
+                * We lost the cache cap, need to truncate the page before
+                * it is unlocked, otherwise we'd truncate it later in the
+                * page truncation thread, possibly losing some data that
+                * raced its way in
+                */
+               if ((issued & CEPH_CAP_FILE_CACHE) == 0)
+                       generic_error_remove_page(inode->i_mapping, page);
+
                unlock_page(page);
        }
        dout("%p wrote+cleaned %d pages\n", inode, wrote);