The only caller locks the page and then has to unlock it again once it returns. Just have ceph_uninline_data do that itself. Also, in the case where we are allocating a local page for this, lock it to help simplify the code a bit. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/ceph/addr.c | 27 ++++++++++++--------------- fs/ceph/super.h | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 859d2cbfeccb..038678963cf9 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -1542,14 +1542,7 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf) ceph_block_sigs(&oldset); if (ci->i_inline_version != CEPH_INLINE_NONE) { - struct page *locked_page = NULL; - if (off == 0) { - lock_page(page); - locked_page = page; - } - err = ceph_uninline_data(inode, locked_page); - if (locked_page) - unlock_page(locked_page); + err = ceph_uninline_data(inode, off == 0 ? page : NULL); if (err < 0) goto out_free; } @@ -1663,7 +1656,7 @@ void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, } } -int ceph_uninline_data(struct inode *inode, struct page *locked_page) +int ceph_uninline_data(struct inode *inode, struct page *provided_page) { struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_fs_client *fsc = ceph_inode_to_client(inode); @@ -1672,6 +1665,7 @@ int ceph_uninline_data(struct inode *inode, struct page *locked_page) u64 len, inline_version; int err = 0; bool from_pagecache = false; + bool allocated_page = false; spin_lock(&ci->i_ceph_lock); inline_version = ci->i_inline_version; @@ -1684,8 +1678,9 @@ int ceph_uninline_data(struct inode *inode, struct page *locked_page) inline_version == CEPH_INLINE_NONE) goto out; - if (locked_page) { - page = locked_page; + if (provided_page) { + page = provided_page; + lock_page(page); WARN_ON(!PageUptodate(page)); } else if (ceph_caps_issued(ci) & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) { @@ -1711,6 +1706,8 @@ int ceph_uninline_data(struct inode *inode, struct page *locked_page) err = -ENOMEM; goto out; } + allocated_page = true; + lock_page(page); err = __ceph_do_getattr(inode, page, CEPH_STAT_CAP_INLINE_DATA, true); if (err < 0) { @@ -1782,11 +1779,11 @@ int ceph_uninline_data(struct inode *inode, struct page *locked_page) if (err == -ECANCELED) err = 0; out: - if (page && page != locked_page) { - if (from_pagecache) { - unlock_page(page); + if (page) { + unlock_page(page); + if (from_pagecache) put_page(page); - } else + else if (allocated_page) __free_pages(page, 0); } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index dd2a242d5d22..0182577e6dae 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -1070,7 +1070,7 @@ extern void ceph_put_fmode(struct ceph_inode_info *ci, int mode); /* addr.c */ extern const struct address_space_operations ceph_aops; extern int ceph_mmap(struct file *file, struct vm_area_struct *vma); -extern int ceph_uninline_data(struct inode *inode, struct page *locked_page); +extern int ceph_uninline_data(struct inode *inode, struct page *provided_page); extern int ceph_pool_perm_check(struct ceph_inode_info *ci, int need); extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc); -- 2.21.0