static int logfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { struct inode *inode = mapping->host; struct page *page; pgoff_t index = pos >> PAGE_CACHE_SHIFT; page = grab_cache_page_write_begin(mapping, index, flags); if (!page) return -ENOMEM; *pagep = page; if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) return 0; if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) { unsigned start = pos & (PAGE_CACHE_SIZE - 1); unsigned end = start + len; /* Reading beyond i_size is simple: memset to zero */ zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE); return 0; } return logfs_readpage_nolock(page); }
static int HgfsDoWriteBegin(struct file *file, // IN: File to be written struct page *page, // IN: Page to be written unsigned pageFrom, // IN: Starting page offset unsigned pageTo) // IN: Ending page offset { ASSERT(page); LOG(6, (KERN_DEBUG "VMware hgfs: %s: off %Lu: %u to %u\n", __func__, (loff_t)page->index << PAGE_CACHE_SHIFT, pageFrom, pageTo)); if (!PageUptodate(page)) { /* * If we are doing a partial write into a new page (beyond end of * file), then intialize it. This allows other writes to this page * to accumulate before we need to write it to the server. */ if (pageTo - pageFrom != PAGE_CACHE_SIZE) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) zero_user_segments(page, 0, pageFrom, pageTo, PAGE_CACHE_SIZE); #else void *kaddr = compat_kmap_atomic(page); memset(kaddr, 0, pageFrom); memset(kaddr + pageTo, 0, PAGE_CACHE_SIZE - pageTo); flush_dcache_page(page); compat_kunmap_atomic(kaddr); #endif } } LOG(6, (KERN_DEBUG "VMware hgfs: %s: returns 0\n", __func__)); return 0; }
static int nfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { unsigned offset = pos & (PAGE_CACHE_SIZE - 1); struct nfs_open_context *ctx = nfs_file_open_context(file); int status; dfprintk(PAGECACHE, "NFS: write_end(%pD2(%lu), %u@%lld)\n", file, mapping->host->i_ino, len, (long long) pos); /* * Zero any uninitialised parts of the page, and then mark the page * as up to date if it turns out that we're extending the file. */ if (!PageUptodate(page)) { unsigned pglen = nfs_page_length(page); unsigned end = offset + len; if (pglen == 0) { zero_user_segments(page, 0, offset, end, PAGE_CACHE_SIZE); SetPageUptodate(page); } else if (end >= pglen) { zero_user_segment(page, end, PAGE_CACHE_SIZE); if (offset == 0) SetPageUptodate(page); } else zero_user_segment(page, pglen, PAGE_CACHE_SIZE); } status = nfs_updatepage(file, page, offset, copied); unlock_page(page); page_cache_release(page); if (status < 0) return status; NFS_I(mapping->host)->write_io += copied; if (nfs_ctx_key_to_expire(ctx)) { status = nfs_wb_all(mapping->host); if (status < 0) return status; } return copied; }
static int nfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { unsigned offset = pos & (PAGE_CACHE_SIZE - 1); int status; dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, mapping->host->i_ino, len, (long long) pos); /* * Zero any uninitialised parts of the page, and then mark the page * as up to date if it turns out that we're extending the file. */ if (!PageUptodate(page)) { unsigned pglen = nfs_page_length(page); unsigned end = offset + len; if (pglen == 0) { zero_user_segments(page, 0, offset, end, PAGE_CACHE_SIZE); SetPageUptodate(page); } else if (end >= pglen) { zero_user_segment(page, end, PAGE_CACHE_SIZE); if (offset == 0) SetPageUptodate(page); } else zero_user_segment(page, pglen, PAGE_CACHE_SIZE); } status = nfs_updatepage(file, page, offset, copied); unlock_page(page); page_cache_release(page); if (status < 0) return status; return copied; }
static int f2fs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { struct inode *inode = mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; struct page *ipage; pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT; struct dnode_of_data dn; int err = 0; trace_f2fs_write_begin(inode, pos, len, flags); f2fs_balance_fs(sbi); /* * We should check this at this moment to avoid deadlock on inode page * and #0 page. The locking rule for inline_data conversion should be: * lock_page(page #0) -> lock_page(inode_page) */ if (index != 0) { err = f2fs_convert_inline_inode(inode); if (err) goto fail; } repeat: page = grab_cache_page_write_begin(mapping, index, flags); if (!page) { err = -ENOMEM; goto fail; } *pagep = page; f2fs_lock_op(sbi); /* check inline_data */ ipage = get_node_page(sbi, inode->i_ino); if (IS_ERR(ipage)) { err = PTR_ERR(ipage); goto unlock_fail; } set_new_dnode(&dn, inode, ipage, ipage, 0); if (f2fs_has_inline_data(inode)) { if (pos + len <= MAX_INLINE_DATA) { read_inline_data(page, ipage); set_inode_flag(F2FS_I(inode), FI_DATA_EXIST); sync_inode_page(&dn); goto put_next; } err = f2fs_convert_inline_page(&dn, page); if (err) goto put_fail; } err = f2fs_get_block(&dn, index); if (err) goto put_fail; put_next: f2fs_put_dnode(&dn); f2fs_unlock_op(sbi); f2fs_wait_on_page_writeback(page, DATA); if (len == PAGE_CACHE_SIZE) goto out_update; if (PageUptodate(page)) goto out_clear; if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) { unsigned start = pos & (PAGE_CACHE_SIZE - 1); unsigned end = start + len; /* Reading beyond i_size is simple: memset to zero */ zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE); goto out_update; } if (dn.data_blkaddr == NEW_ADDR) { zero_user_segment(page, 0, PAGE_CACHE_SIZE); } else { struct f2fs_io_info fio = { .sbi = sbi, .type = DATA, .rw = READ_SYNC, .blk_addr = dn.data_blkaddr, .page = page, .encrypted_page = NULL, }; err = f2fs_submit_page_bio(&fio); if (err) goto fail; lock_page(page); if (unlikely(!PageUptodate(page))) { err = -EIO; goto fail; } if (unlikely(page->mapping != mapping)) { f2fs_put_page(page, 1); goto repeat; } /* avoid symlink page */ if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) { err = f2fs_decrypt_one(inode, page); if (err) goto fail; } } out_update: SetPageUptodate(page); out_clear: clear_cold_data(page); return 0; put_fail: f2fs_put_dnode(&dn); unlock_fail: f2fs_unlock_op(sbi); fail: f2fs_put_page(page, 1); f2fs_write_failed(mapping, pos + len); return err; } static int f2fs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { struct inode *inode = page->mapping->host; trace_f2fs_write_end(inode, pos, len, copied); set_page_dirty(page); if (pos + copied > i_size_read(inode)) { i_size_write(inode, pos + copied); mark_inode_dirty(inode); update_inode_page(inode); } f2fs_put_page(page, 1); return copied; } static int check_direct_IO(struct inode *inode, struct iov_iter *iter, loff_t offset) { unsigned blocksize_mask = inode->i_sb->s_blocksize - 1; if (offset & blocksize_mask) return -EINVAL; if (iov_iter_alignment(iter) & blocksize_mask) return -EINVAL; return 0; }
static int f2fs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { struct inode *inode = mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; struct page *ipage; pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT; struct dnode_of_data dn; int err = 0; trace_f2fs_write_begin(inode, pos, len, flags); f2fs_balance_fs(sbi); /* * We should check this at this moment to avoid deadlock on inode page * and #0 page. The locking rule for inline_data conversion should be: * lock_page(page #0) -> lock_page(inode_page) */ if (index != 0) { err = f2fs_convert_inline_inode(inode); if (err) goto fail; } repeat: page = grab_cache_page_write_begin(mapping, index, flags); if (!page) { err = -ENOMEM; goto fail; } *pagep = page; f2fs_lock_op(sbi); /* check inline_data */ ipage = get_node_page(sbi, inode->i_ino); if (IS_ERR(ipage)) { err = PTR_ERR(ipage); goto unlock_fail; } set_new_dnode(&dn, inode, ipage, ipage, 0); if (f2fs_has_inline_data(inode)) { if (pos + len <= MAX_INLINE_DATA) { read_inline_data(page, ipage); set_inode_flag(F2FS_I(inode), FI_DATA_EXIST); sync_inode_page(&dn); goto put_next; } err = f2fs_convert_inline_page(&dn, page); if (err) goto put_fail; } err = f2fs_get_block(&dn, index); if (err) goto put_fail; put_next: f2fs_put_dnode(&dn); f2fs_unlock_op(sbi); f2fs_wait_on_page_writeback(page, DATA); if (len == PAGE_CACHE_SIZE) goto out_update; if (PageUptodate(page)) goto out_clear; if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) { unsigned start = pos & (PAGE_CACHE_SIZE - 1); unsigned end = start + len; /* Reading beyond i_size is simple: memset to zero */ zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE); goto out_update; } if (dn.data_blkaddr == NEW_ADDR) { zero_user_segment(page, 0, PAGE_CACHE_SIZE); } else { struct f2fs_io_info fio = { .sbi = sbi, .type = DATA, .rw = READ_SYNC, .blk_addr = dn.data_blkaddr, .page = page, .encrypted_page = NULL, }; err = f2fs_submit_page_bio(&fio); if (err) goto fail; lock_page(page); if (unlikely(!PageUptodate(page))) { err = -EIO; goto fail; } if (unlikely(page->mapping != mapping)) { f2fs_put_page(page, 1); goto repeat; } /* avoid symlink page */ if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) { err = f2fs_decrypt_one(inode, page); if (err) goto fail; } } out_update: SetPageUptodate(page); out_clear: clear_cold_data(page); return 0; put_fail: f2fs_put_dnode(&dn); unlock_fail: f2fs_unlock_op(sbi); fail: f2fs_put_page(page, 1); f2fs_write_failed(mapping, pos + len); return err; } static int f2fs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { struct inode *inode = page->mapping->host; trace_f2fs_write_end(inode, pos, len, copied); set_page_dirty(page); if (pos + copied > i_size_read(inode)) { i_size_write(inode, pos + copied); mark_inode_dirty(inode); update_inode_page(inode); } f2fs_put_page(page, 1); return copied; } static ssize_t check_direct_IO(struct inode *inode, int rw, const struct iovec *iov, loff_t offset, unsigned long nr_segs) { unsigned blocksize_mask = inode->i_sb->s_blocksize - 1; int seg, i; size_t size; unsigned long addr; ssize_t retval = -EINVAL; loff_t end = offset; if (offset & blocksize_mask) return -EINVAL; /* Check the memory alignment. Blocks cannot straddle pages */ for (seg = 0; seg < nr_segs; seg++) { addr = (unsigned long)iov[seg].iov_base; size = iov[seg].iov_len; end += size; if ((addr & blocksize_mask) || (size & blocksize_mask)) goto out; /* If this is a write we don't need to check anymore */ if (rw & WRITE) continue; /* * Check to make sure we don't have duplicate iov_base's in this * iovec, if so return EINVAL, otherwise we'll get csum errors * when reading back. */ for (i = seg + 1; i < nr_segs; i++) { if (iov[seg].iov_base == iov[i].iov_base) goto out; } } retval = 0; out: return retval; }