From: Martin Brandenburg <martin@xxxxxxxxxxxx> With this and the previous commit, OrangeFS is capable of writing through the page cache. Signed-off-by: Martin Brandenburg <martin@xxxxxxxxxxxx> --- fs/orangefs/file.c | 132 +++++++++++++++++++++++----------------------------- fs/orangefs/inode.c | 2 + fs/orangefs/super.c | 8 ++++ 3 files changed, 67 insertions(+), 75 deletions(-) diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index d80e1e6c1d95..200c72c21b0b 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -397,69 +397,11 @@ static ssize_t orangefs_file_read_iter(struct kiocb *iocb, return generic_file_read_iter(iocb, iter); } -static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) +static ssize_t orangefs_file_write_iter(struct kiocb *iocb, + struct iov_iter *iter) { - struct file *file = iocb->ki_filp; - loff_t pos; - ssize_t rc; - - BUG_ON(iocb->private); - - gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_write_iter\n"); - - inode_lock(file->f_mapping->host); - - /* Make sure generic_write_checks sees an up to date inode size. */ - if (file->f_flags & O_APPEND) { - rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1, - STATX_SIZE); - if (rc == -ESTALE) - rc = -EIO; - if (rc) { - gossip_err("%s: orangefs_inode_getattr failed, " - "rc:%zd:.\n", __func__, rc); - goto out; - } - } - - if (file->f_pos > i_size_read(file->f_mapping->host)) - orangefs_i_size_write(file->f_mapping->host, file->f_pos); - - rc = generic_write_checks(iocb, iter); - - if (rc <= 0) { - gossip_err("%s: generic_write_checks failed, rc:%zd:.\n", - __func__, rc); - goto out; - } - - /* - * if we are appending, generic_write_checks would have updated - * pos to the end of the file, so we will wait till now to set - * pos... - */ - pos = *(&iocb->ki_pos); - - rc = do_readv_writev(ORANGEFS_IO_WRITE, - file, - &pos, - iter); - if (rc < 0) { - gossip_err("%s: do_readv_writev failed, rc:%zd:.\n", - __func__, rc); - goto out; - } - - iocb->ki_pos = pos; orangefs_stats.writes++; - - if (pos > i_size_read(file->f_mapping->host)) - orangefs_i_size_write(file->f_mapping->host, pos); - -out: - - inode_unlock(file->f_mapping->host); - return rc; + return generic_file_write_iter(iocb, iter); } /* @@ -554,9 +496,6 @@ static int orangefs_file_mmap(struct file *file, struct vm_area_struct *vma) (char *)file->f_path.dentry->d_name.name : (char *)"Unknown")); - if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) - return -EINVAL; - /* set the sequential readahead hint */ vma->vm_flags |= VM_SEQ_READ; vma->vm_flags &= ~VM_RAND_READ; @@ -579,9 +518,8 @@ static int orangefs_file_release(struct inode *inode, struct file *file) file); /* - * remove all associated inode pages from the page cache and - * readahead cache (if any); this forces an expensive refresh of - * data for the next caller of mmap (or 'get_block' accesses) + * remove all associated inode pages from the readahead cache + * (if any) */ if (file_inode(file) && file_inode(file)->i_mapping && @@ -594,8 +532,6 @@ static int orangefs_file_release(struct inode *inode, struct file *file) gossip_debug(GOSSIP_INODE_DEBUG, "flush_racache finished\n"); } - truncate_inode_pages(file_inode(file)->i_mapping, - 0); } return 0; } @@ -707,6 +643,41 @@ const struct file_operations orangefs_file_operations = { .fsync = orangefs_fsync, }; + +static int orangefs_writepage(struct page *page, + struct writeback_control *wbc) +{ + struct inode *inode = page->mapping->host; + struct iov_iter iter; + struct bio_vec bv; + loff_t off; + size_t len; + ssize_t r; + + off = page_offset(page); + len = i_size_read(inode); + if (off + PAGE_SIZE > len) + len = len - off; + else + len = PAGE_SIZE; + + bv.bv_page = page; + bv.bv_len = len; + bv.bv_offset = 0; + iov_iter_bvec(&iter, ITER_BVEC | WRITE, &bv, 1, len); + + set_page_writeback(page); + + r = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, + len, 0); + if (r < 0) + mapping_set_error(inode->i_mapping, r); + + end_page_writeback(page); + unlock_page(page); + return 0; +} + static int orangefs_readpage(struct file *file, struct page *page) { int ret; @@ -752,6 +723,17 @@ static int orangefs_readpage(struct file *file, struct page *page) return ret; } +static int orangefs_write_end(struct file *file, + struct address_space *mapping, loff_t pos, unsigned len, + unsigned copied, struct page *page, void *fsdata) +{ + int r; + r = simple_write_end(file, mapping, pos, len, copied, page, + fsdata); + mark_inode_dirty_sync(file_inode(file)); + return r; +} + static void orangefs_invalidatepage(struct page *page, unsigned int offset, unsigned int length) @@ -781,17 +763,17 @@ static ssize_t orangefs_direct_IO(struct kiocb *iocb, { struct file *file = iocb->ki_filp; loff_t pos = *(&iocb->ki_pos); - /* - * This cannot happen until write_iter becomes - * generic_file_write_iter. - */ - BUG_ON(iov_iter_rw(iter) != READ); - return do_readv_writev(ORANGEFS_IO_READ, file, &pos, iter); + return do_readv_writev(iov_iter_rw(iter) == WRITE ? + ORANGEFS_IO_WRITE : ORANGEFS_IO_READ, file, &pos, iter); } /** ORANGEFS2 implementation of address space operations */ const struct address_space_operations orangefs_address_operations = { + .writepage = orangefs_writepage, .readpage = orangefs_readpage, + .set_page_dirty = __set_page_dirty_nobuffers, + .write_begin = simple_write_begin, + .write_end = orangefs_write_end, .invalidatepage = orangefs_invalidatepage, .releasepage = orangefs_releasepage, .direct_IO = orangefs_direct_IO, diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 2c4f57c5d830..231242a4856e 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -65,6 +65,8 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr) r = setattr_prepare(dentry, iattr); if (r) return r; + if (d_is_reg(dentry)) + filemap_write_and_wait(d_inode(dentry)->i_mapping); if (iattr->ia_valid & ATTR_SIZE) if (i_size_read(d_inode(dentry)) != iattr->ia_size) iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME; diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index 5c17709862ab..5c1a343ba026 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -315,11 +315,19 @@ static int orangefs_write_inode(struct inode *inode, return r; } +static void orangefs_evict_inode(struct inode *inode) +{ + truncate_inode_pages_final(&inode->i_data); + clear_inode(inode); + filemap_fdatawrite(&inode->i_data); +} + static const struct super_operations orangefs_s_ops = { .alloc_inode = orangefs_alloc_inode, .destroy_inode = orangefs_destroy_inode, .write_inode = orangefs_write_inode, .drop_inode = generic_drop_inode, + .evict_inode = orangefs_evict_inode, .statfs = orangefs_statfs, .remount_fs = orangefs_remount_fs, .show_options = orangefs_show_options, -- 2.15.1