@@ -1234,29 +1234,30 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
pgoff_t index = pos >> PAGE_SHIFT;
int r;
+ /*
+ * Uninlining should have already been done and everything updated, EXCEPT
+ * for inline_version sent to the MDS.
+ */
if (ci->i_inline_version != CEPH_INLINE_NONE) {
- /*
- * In principle, we should never get here, as the inode should have been uninlined
- * before we're allowed to write to the page (in write_iter or page_mkwrite).
- */
- WARN_ONCE(1, "ceph: write_begin called on still-inlined inode!\n");
+ page = grab_cache_page_write_begin(mapping, index, flags);
+ if (!page)
+ return -ENOMEM;
/*
- * Uptodate inline data should have been added
- * into page cache while getting Fcr caps.
+ * The inline_version on a new inode is set to 1. If that's the
+ * case, then the page is brand new and isn't yet Uptodate.
*/
- if (index == 0) {
- r = -EINVAL;
+ r = 0;
+ if (index == 0 && ci->i_inline_version != 1) {
+ if (!PageUptodate(page)) {
+ WARN_ONCE(1, "ceph: write_begin called on still-inlined inode (inline_version %llu)!\n",
+ ci->i_inline_version);
+ r = -EINVAL;
+ }
goto out;
}
-
- page = grab_cache_page_write_begin(mapping, index, flags);
- if (!page)
- return -ENOMEM;
-
zero_user_segment(page, 0, PAGE_SIZE);
SetPageUptodate(page);
- r = 0;
goto out;
}
@@ -1442,9 +1443,6 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
return ret;
}
-/*
- * Reuse write_begin here for simplicity.
- */
static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
Patrick saw some testcase failures with inlined data enabled. While it is true that the data is uninlined before write_begin is called, the i_inline_version is not updated until much later, after the write is complete, when the caps are dirtied. Fix the code to allow for write_begin on the first page of a still-inlined inode, as long as the page is still Uptodate. Reported-by: Patrick Donnelly <pdonnell@redhat.com> Signed-off-by: Jeff Layton <jlayton@kernel.org> --- fs/ceph/addr.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) This is a fix for the netfs conversion. If this tests out OK, I'll plan to fold this fix into the write_begin conversion.