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@xxxxxxxxxx> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- 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. diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 7b0980980ac0..f7c3247616d9 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -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; -- 2.29.2