diff options
Diffstat (limited to 'fs/ntfs3/inode.c')
-rw-r--r-- | fs/ntfs3/inode.c | 119 |
1 files changed, 62 insertions, 57 deletions
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 0f1664db94ad..6b0bdc474e76 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -18,7 +18,7 @@ #include "ntfs_fs.h" /* - * ntfs_read_mft - Read record and parses MFT. + * ntfs_read_mft - Read record and parse MFT. */ static struct inode *ntfs_read_mft(struct inode *inode, const struct cpu_str *name, @@ -441,10 +441,9 @@ end_enum: * Usually a hard links to directories are disabled. */ inode->i_op = &ntfs_dir_inode_operations; - if (is_legacy_ntfs(inode->i_sb)) - inode->i_fop = &ntfs_legacy_dir_operations; - else - inode->i_fop = &ntfs_dir_operations; + inode->i_fop = unlikely(is_legacy_ntfs(sb)) ? + &ntfs_legacy_dir_operations : + &ntfs_dir_operations; ni->i_valid = 0; } else if (S_ISLNK(mode)) { ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; @@ -454,10 +453,9 @@ end_enum: } else if (S_ISREG(mode)) { ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; inode->i_op = &ntfs_file_inode_operations; - if (is_legacy_ntfs(inode->i_sb)) - inode->i_fop = &ntfs_legacy_file_operations; - else - inode->i_fop = &ntfs_file_operations; + inode->i_fop = unlikely(is_legacy_ntfs(sb)) ? + &ntfs_legacy_file_operations : + &ntfs_file_operations; inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops; if (ino != MFT_REC_MFT) @@ -580,10 +578,11 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, bh->b_blocknr = RESIDENT_LCN; bh->b_size = block_size; if (!folio) { + /* direct io (read) or bmap call */ err = 0; } else { ni_lock(ni); - err = attr_data_read_resident(ni, &folio->page); + err = attr_data_read_resident(ni, folio); ni_unlock(ni); if (!err) @@ -710,25 +709,24 @@ static sector_t ntfs_bmap(struct address_space *mapping, sector_t block) static int ntfs_read_folio(struct file *file, struct folio *folio) { - struct page *page = &folio->page; int err; - struct address_space *mapping = page->mapping; + struct address_space *mapping = folio->mapping; struct inode *inode = mapping->host; struct ntfs_inode *ni = ntfs_i(inode); if (is_resident(ni)) { ni_lock(ni); - err = attr_data_read_resident(ni, page); + err = attr_data_read_resident(ni, folio); ni_unlock(ni); if (err != E_NTFS_NONRESIDENT) { - unlock_page(page); + folio_unlock(folio); return err; } } if (is_compressed(ni)) { ni_lock(ni); - err = ni_readpage_cmpr(ni, page); + err = ni_readpage_cmpr(ni, folio); ni_unlock(ni); return err; } @@ -872,7 +870,7 @@ static int ntfs_resident_writepage(struct folio *folio, return -EIO; ni_lock(ni); - ret = attr_data_write_resident(ni, &folio->page); + ret = attr_data_write_resident(ni, folio); ni_unlock(ni); if (ret != E_NTFS_NONRESIDENT) @@ -914,24 +912,25 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping, *pagep = NULL; if (is_resident(ni)) { - struct page *page = - grab_cache_page_write_begin(mapping, pos >> PAGE_SHIFT); + struct folio *folio = __filemap_get_folio( + mapping, pos >> PAGE_SHIFT, FGP_WRITEBEGIN, + mapping_gfp_mask(mapping)); - if (!page) { - err = -ENOMEM; + if (IS_ERR(folio)) { + err = PTR_ERR(folio); goto out; } ni_lock(ni); - err = attr_data_read_resident(ni, page); + err = attr_data_read_resident(ni, folio); ni_unlock(ni); if (!err) { - *pagep = page; + *pagep = &folio->page; goto out; } - unlock_page(page); - put_page(page); + folio_unlock(folio); + folio_put(folio); if (err != E_NTFS_NONRESIDENT) goto out; @@ -950,6 +949,7 @@ out: int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, u32 len, u32 copied, struct page *page, void *fsdata) { + struct folio *folio = page_folio(page); struct inode *inode = mapping->host; struct ntfs_inode *ni = ntfs_i(inode); u64 valid = ni->i_valid; @@ -958,26 +958,26 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, if (is_resident(ni)) { ni_lock(ni); - err = attr_data_write_resident(ni, page); + err = attr_data_write_resident(ni, folio); ni_unlock(ni); if (!err) { + struct buffer_head *head = folio_buffers(folio); dirty = true; - /* Clear any buffers in page. */ - if (page_has_buffers(page)) { - struct buffer_head *head, *bh; + /* Clear any buffers in folio. */ + if (head) { + struct buffer_head *bh = head; - bh = head = page_buffers(page); do { clear_buffer_dirty(bh); clear_buffer_mapped(bh); set_buffer_uptodate(bh); } while (head != (bh = bh->b_this_page)); } - SetPageUptodate(page); + folio_mark_uptodate(folio); err = copied; } - unlock_page(page); - put_page(page); + folio_unlock(folio); + folio_put(folio); } else { err = generic_write_end(file, mapping, pos, len, copied, page, fsdata); @@ -1093,33 +1093,31 @@ int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, if (!ret && i2) ret = writeback_inode(i2); if (!ret) - ret = sync_blockdev_nowait(sb->s_bdev); + ret = filemap_flush(sb->s_bdev_file->f_mapping); return ret; } -int inode_write_data(struct inode *inode, const void *data, size_t bytes) +/* + * Helper function to read file. + */ +int inode_read_data(struct inode *inode, void *data, size_t bytes) { pgoff_t idx; + struct address_space *mapping = inode->i_mapping; - /* Write non resident data. */ for (idx = 0; bytes; idx++) { size_t op = bytes > PAGE_SIZE ? PAGE_SIZE : bytes; - struct page *page = ntfs_map_page(inode->i_mapping, idx); + struct page *page = read_mapping_page(mapping, idx, NULL); + void *kaddr; if (IS_ERR(page)) return PTR_ERR(page); - lock_page(page); - WARN_ON(!PageUptodate(page)); - ClearPageUptodate(page); - - memcpy(page_address(page), data, op); - - flush_dcache_page(page); - SetPageUptodate(page); - unlock_page(page); + kaddr = kmap_atomic(page); + memcpy(data, kaddr, op); + kunmap_atomic(kaddr); - ntfs_unmap_page(page); + put_page(page); bytes -= op; data = Add2Ptr(data, PAGE_SIZE); @@ -1508,7 +1506,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8); attr->name_off = SIZEOF_NONRESIDENT_EX_LE; attr->flags = ATTR_FLAG_COMPRESSED; - attr->nres.c_unit = COMPRESSION_UNIT; + attr->nres.c_unit = NTFS_LZNT_CUNIT; asize = SIZEOF_NONRESIDENT_EX + 8; } else { attr->size = cpu_to_le32(SIZEOF_NONRESIDENT + 8); @@ -1559,7 +1557,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, /* * Below function 'ntfs_save_wsl_perm' requires 0x78 bytes. - * It is good idea to keep extened attributes resident. + * It is good idea to keep extended attributes resident. */ if (asize + t16 + 0x78 + 8 > sbi->record_size) { CLST alen; @@ -1628,10 +1626,9 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, if (S_ISDIR(mode)) { inode->i_op = &ntfs_dir_inode_operations; - if (is_legacy_ntfs(inode->i_sb)) - inode->i_fop = &ntfs_legacy_dir_operations; - else - inode->i_fop = &ntfs_dir_operations; + inode->i_fop = unlikely(is_legacy_ntfs(sb)) ? + &ntfs_legacy_dir_operations : + &ntfs_dir_operations; } else if (S_ISLNK(mode)) { inode->i_op = &ntfs_link_inode_operations; inode->i_fop = NULL; @@ -1640,10 +1637,9 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, inode_nohighmem(inode); } else if (S_ISREG(mode)) { inode->i_op = &ntfs_file_inode_operations; - if (is_legacy_ntfs(inode->i_sb)) - inode->i_fop = &ntfs_legacy_file_operations; - else - inode->i_fop = &ntfs_file_operations; + inode->i_fop = unlikely(is_legacy_ntfs(sb)) ? + &ntfs_legacy_file_operations : + &ntfs_file_operations; inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr : &ntfs_aops; init_rwsem(&ni->file.run_lock); @@ -1668,7 +1664,9 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, * The packed size of extended attribute is stored in direntry too. * 'fname' here points to inside new_de. */ - ntfs_save_wsl_perm(inode, &fname->dup.ea_size); + err = ntfs_save_wsl_perm(inode, &fname->dup.ea_size); + if (err) + goto out6; /* * update ea_size in file_name attribute too. @@ -1712,6 +1710,12 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, goto out2; out6: + attr = ni_find_attr(ni, NULL, NULL, ATTR_EA, NULL, 0, NULL, NULL); + if (attr && attr->non_res) { + /* Delete ATTR_EA, if non-resident. */ + attr_set_size(ni, ATTR_EA, NULL, 0, NULL, 0, NULL, false, NULL); + } + if (rp_inserted) ntfs_remove_reparse(sbi, IO_REPARSE_TAG_SYMLINK, &new_de->ref); @@ -2133,5 +2137,6 @@ const struct address_space_operations ntfs_aops = { const struct address_space_operations ntfs_aops_cmpr = { .read_folio = ntfs_read_folio, .readahead = ntfs_readahead, + .dirty_folio = block_dirty_folio, }; // clang-format on |