From 34abb4f6fd29ec70b8c7ff33c0721cd3eb1c7a20 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 16 May 2024 20:37:53 +0300 Subject: fs/ntfs3: Remove unused function At the moment, the function turned out to be unused, so I removed it. Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 30 ------------------------------ fs/ntfs3/ntfs_fs.h | 1 - 2 files changed, 31 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 0f1664db94ad..6dc51faeef8d 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1097,36 +1097,6 @@ int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, return ret; } -int inode_write_data(struct inode *inode, const void *data, size_t bytes) -{ - pgoff_t idx; - - /* 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); - - 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); - - ntfs_unmap_page(page); - - bytes -= op; - data = Add2Ptr(data, PAGE_SIZE); - } - return 0; -} - /* * ntfs_reparse_bytes * diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index f9ed6d2b065d..ee0c1b76e812 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -716,7 +716,6 @@ int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc); int ntfs_sync_inode(struct inode *inode); int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2); -int inode_write_data(struct inode *inode, const void *data, size_t bytes); int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, const struct cpu_str *uni, umode_t mode, dev_t dev, const char *symname, u32 size, -- cgit v1.2.3 From 487f8d482a7e51a640b8f955a398f906a4f83951 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 16 May 2024 00:41:02 +0300 Subject: fs/ntfs3: Merge synonym COMPRESSION_UNIT and NTFS_LZNT_CUNIT COMPRESSION_UNIT and NTFS_LZNT_CUNIT mean the same thing (1u< --- fs/ntfs3/attrib.c | 2 +- fs/ntfs3/frecord.c | 2 +- fs/ntfs3/fslog.c | 2 +- fs/ntfs3/inode.c | 2 +- fs/ntfs3/ntfs.h | 3 --- 5 files changed, 4 insertions(+), 7 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 8e6bcdf99770..9ccec4519074 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -254,7 +254,7 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr, align = sbi->cluster_size; if (is_attr_compressed(attr)) - align <<= COMPRESSION_UNIT; + align <<= NTFS_LZNT_CUNIT; len = (rsize + align - 1) >> sbi->cluster_bits; run_init(run); diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 0008670939a4..4822cfd6351c 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1501,7 +1501,7 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type, if (is_ext) { if (flags & ATTR_FLAG_COMPRESSED) - attr->nres.c_unit = COMPRESSION_UNIT; + attr->nres.c_unit = NTFS_LZNT_CUNIT; attr->nres.total_size = attr->nres.alloc_size; } diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index d7807d255dfe..763644f90094 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -2992,7 +2992,7 @@ static struct ATTRIB *attr_create_nonres_log(struct ntfs_sb_info *sbi, if (is_ext) { attr->name_off = SIZEOF_NONRESIDENT_EX_LE; if (is_attr_compressed(attr)) - attr->nres.c_unit = COMPRESSION_UNIT; + attr->nres.c_unit = NTFS_LZNT_CUNIT; attr->nres.run_off = cpu_to_le16(SIZEOF_NONRESIDENT_EX + name_size); diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 6dc51faeef8d..66407045e69a 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1478,7 +1478,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); diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index 3d6143c7abc0..1f2cdb0dbbe1 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h @@ -82,9 +82,6 @@ typedef u32 CLST; #define RESIDENT_LCN ((CLST)-2) #define COMPRESSED_LCN ((CLST)-3) -#define COMPRESSION_UNIT 4 -#define COMPRESS_MAX_CLUSTER 0x1000 - enum RECORD_NUM { MFT_REC_MFT = 0, MFT_REC_MIRR = 1, -- cgit v1.2.3 From 220cf0498bbf401e6cedc275676371f808f9bf10 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 May 2024 11:23:51 +0300 Subject: fs/ntfs3: Simplify initialization of $AttrDef and $UpCase Replaced the two loops reading $AttrDef and $UpCase with the inode_read_data() function. Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 28 +++++++++++++++++++++++++ fs/ntfs3/ntfs_fs.h | 17 +--------------- fs/ntfs3/super.c | 60 +++++++++++++++++++++--------------------------------- 3 files changed, 52 insertions(+), 53 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 66407045e69a..2a7348b7a167 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1097,6 +1097,34 @@ int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, return ret; } +/* + * 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; + + for (idx = 0; bytes; idx++) { + size_t op = bytes > PAGE_SIZE ? PAGE_SIZE : bytes; + struct page *page = read_mapping_page(mapping, idx, NULL); + void *kaddr; + + if (IS_ERR(page)) + return PTR_ERR(page); + + kaddr = kmap_atomic(page); + memcpy(data, kaddr, op); + kunmap_atomic(kaddr); + + put_page(page); + + bytes -= op; + data = Add2Ptr(data, PAGE_SIZE); + } + return 0; +} + /* * ntfs_reparse_bytes * diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index ee0c1b76e812..3583d47b95da 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -716,6 +716,7 @@ int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc); int ntfs_sync_inode(struct inode *inode); int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2); +int inode_read_data(struct inode *inode, void *data, size_t bytes); int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, const struct cpu_str *uni, umode_t mode, dev_t dev, const char *symname, u32 size, @@ -909,22 +910,6 @@ static inline bool ntfs_is_meta_file(struct ntfs_sb_info *sbi, CLST rno) rno == sbi->usn_jrnl_no; } -static inline void ntfs_unmap_page(struct page *page) -{ - kunmap(page); - put_page(page); -} - -static inline struct page *ntfs_map_page(struct address_space *mapping, - unsigned long index) -{ - struct page *page = read_mapping_page(mapping, index, NULL); - - if (!IS_ERR(page)) - kmap(page); - return page; -} - static inline size_t wnd_zone_bit(const struct wnd_bitmap *wnd) { return wnd->zone_bit; diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 27fbde2701b6..6c9e5fe8ce81 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1163,7 +1163,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) CLST vcn, lcn, len; struct ATTRIB *attr; const struct VOLUME_INFO *info; - u32 idx, done, bytes; + u32 done, bytes; struct ATTR_DEF_ENTRY *t; u16 *shared; struct MFT_REF ref; @@ -1435,31 +1435,22 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) goto put_inode_out; } - for (done = idx = 0; done < bytes; done += PAGE_SIZE, idx++) { - unsigned long tail = bytes - done; - struct page *page = ntfs_map_page(inode->i_mapping, idx); + /* Read the entire file. */ + err = inode_read_data(inode, sbi->def_table, bytes); + if (err) { + ntfs_err(sb, "Failed to read $AttrDef (%d).", err); + goto put_inode_out; + } - if (IS_ERR(page)) { - err = PTR_ERR(page); - ntfs_err(sb, "Failed to read $AttrDef (%d).", err); - goto put_inode_out; - } - memcpy(Add2Ptr(t, done), page_address(page), - min(PAGE_SIZE, tail)); - ntfs_unmap_page(page); - - if (!idx && ATTR_STD != t->type) { - ntfs_err(sb, "$AttrDef is corrupted."); - err = -EINVAL; - goto put_inode_out; - } + if (ATTR_STD != t->type) { + ntfs_err(sb, "$AttrDef is corrupted."); + err = -EINVAL; + goto put_inode_out; } t += 1; sbi->def_entries = 1; done = sizeof(struct ATTR_DEF_ENTRY); - sbi->reparse.max_size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; - sbi->ea_max_size = 0x10000; /* default formatter value */ while (done + sizeof(struct ATTR_DEF_ENTRY) <= bytes) { u32 t32 = le32_to_cpu(t->type); @@ -1495,27 +1486,22 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) goto put_inode_out; } - for (idx = 0; idx < (0x10000 * sizeof(short) >> PAGE_SHIFT); idx++) { - const __le16 *src; - u16 *dst = Add2Ptr(sbi->upcase, idx << PAGE_SHIFT); - struct page *page = ntfs_map_page(inode->i_mapping, idx); - - if (IS_ERR(page)) { - err = PTR_ERR(page); - ntfs_err(sb, "Failed to read $UpCase (%d).", err); - goto put_inode_out; - } - - src = page_address(page); + /* Read the entire file. */ + err = inode_read_data(inode, sbi->upcase, 0x10000 * sizeof(short)); + if (err) { + ntfs_err(sb, "Failed to read $UpCase (%d).", err); + goto put_inode_out; + } #ifdef __BIG_ENDIAN - for (i = 0; i < PAGE_SIZE / sizeof(u16); i++) + { + const __le16 *src = sbi->upcase; + u16 *dst = sbi->upcase; + + for (i = 0; i < 0x10000; i++) *dst++ = le16_to_cpu(*src++); -#else - memcpy(dst, src, PAGE_SIZE); -#endif - ntfs_unmap_page(page); } +#endif shared = ntfs_set_shared(sbi->upcase, 0x10000 * sizeof(short)); if (shared && sbi->upcase != shared) { -- cgit v1.2.3 From 2c2814d0dafc13153c880278e3a3ca4c891c1d51 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 16 May 2024 20:55:12 +0300 Subject: fs/ntfs3: Use macros NTFS_LABEL_MAX_LENGTH instead of hardcoded value To check the length of the volume label, the existing constant NTFS_LABEL_MAX_LENGTH could be used. Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 626d3f2c7e2d..0fa636038b4e 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -2650,8 +2650,8 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) { int err; struct ATTRIB *attr; + u32 uni_bytes; struct ntfs_inode *ni = sbi->volume.ni; - const u8 max_ulen = 0x80; /* TODO: use attrdef to get maximum length */ /* Allocate PATH_MAX bytes. */ struct cpu_str *uni = __getname(); @@ -2663,7 +2663,8 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) if (err < 0) goto out; - if (uni->len > max_ulen) { + uni_bytes = uni->len * sizeof(u16); + if (uni_bytes > NTFS_LABEL_MAX_LENGTH * sizeof(u16)) { ntfs_warn(sbi->sb, "new label is too long"); err = -EFBIG; goto out; @@ -2674,13 +2675,13 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len) /* Ignore any errors. */ ni_remove_attr(ni, ATTR_LABEL, NULL, 0, false, NULL); - err = ni_insert_resident(ni, uni->len * sizeof(u16), ATTR_LABEL, NULL, - 0, &attr, NULL, NULL); + err = ni_insert_resident(ni, uni_bytes, ATTR_LABEL, NULL, 0, &attr, + NULL, NULL); if (err < 0) goto unlock_out; /* write new label in on-disk struct. */ - memcpy(resident_data(attr), uni->name, uni->len * sizeof(u16)); + memcpy(resident_data(attr), uni->name, uni_bytes); /* update cached value of current label. */ if (len >= ARRAY_SIZE(sbi->volume.label)) -- cgit v1.2.3 From 3cdad499ac10556fc368a909d35ec821c52ea00e Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 16 May 2024 00:56:47 +0300 Subject: fs/ntfs3: Remove unused macros MAXIMUM_REPARSE_DATA_BUFFER_SIZE MAXIMUM_REPARSE_DATA_BUFFER_SIZE is not used in the code. Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index 1f2cdb0dbbe1..a5ca08db6dc5 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h @@ -999,9 +999,6 @@ struct REPARSE_POINT { static_assert(sizeof(struct REPARSE_POINT) == 0x18); -/* Maximum allowed size of the reparse data. */ -#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) - /* * The value of the following constant needs to satisfy the following * conditions: -- cgit v1.2.3 From 25610ff98d4a34e6a85cbe4fd8671be6b0829f8f Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 16 May 2024 01:10:01 +0300 Subject: fs/ntfs3: Fix transform resident to nonresident for compressed files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сorrected calculation of required space len (in clusters) for attribute data storage in case of compression. Fixes: be71b5cba2e64 ("fs/ntfs3: Add attrib operations") Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 9ccec4519074..8638248d80d9 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -231,7 +231,7 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr, struct ntfs_sb_info *sbi; struct ATTRIB *attr_s; struct MFT_REC *rec; - u32 used, asize, rsize, aoff, align; + u32 used, asize, rsize, aoff; bool is_data; CLST len, alen; char *next; @@ -252,10 +252,13 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr, rsize = le32_to_cpu(attr->res.data_size); is_data = attr->type == ATTR_DATA && !attr->name_len; - align = sbi->cluster_size; - if (is_attr_compressed(attr)) - align <<= NTFS_LZNT_CUNIT; - len = (rsize + align - 1) >> sbi->cluster_bits; + /* len - how many clusters required to store 'rsize' bytes */ + if (is_attr_compressed(attr)) { + u8 shift = sbi->cluster_bits + NTFS_LZNT_CUNIT; + len = ((rsize + (1u << shift) - 1) >> shift) << NTFS_LZNT_CUNIT; + } else { + len = bytes_to_cluster(sbi, rsize); + } run_init(run); -- cgit v1.2.3 From 69943484b95267c94331cba41e9e64ba7b24f136 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 20:07:44 +0300 Subject: fs/ntfs3: Deny getting attr data block in compressed frame Attempting to retrieve an attribute data block in a compressed frame is ignored. Fixes: be71b5cba2e64 ("fs/ntfs3: Add attrib operations") Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 8638248d80d9..7918ab1a3f35 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -975,6 +975,19 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, if (err) goto out; + /* Check for compressed frame. */ + err = attr_is_frame_compressed(ni, attr, vcn >> NTFS_LZNT_CUNIT, &hint); + if (err) + goto out; + + if (hint) { + /* if frame is compressed - don't touch it. */ + *lcn = COMPRESSED_LCN; + *len = hint; + err = -EOPNOTSUPP; + goto out; + } + if (!*len) { if (run_lookup_entry(run, vcn, lcn, len, NULL)) { if (*lcn != SPARSE_LCN || !new) -- cgit v1.2.3 From 1c308ace1fd6de93bd0b7e1a5e8963ab27e2c016 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 20:36:03 +0300 Subject: fs/ntfs3: Missed NI_FLAG_UPDATE_PARENT setting Fixes: be71b5cba2e64 ("fs/ntfs3: Add attrib operations") Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 7918ab1a3f35..0d13da5523b1 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1738,6 +1738,7 @@ repack: attr_b->nres.total_size = cpu_to_le64(total_size); inode_set_bytes(&ni->vfs_inode, total_size); + ni->ni_flags |= NI_FLAG_UPDATE_PARENT; mi_b->dirty = true; mark_inode_dirty(&ni->vfs_inode); -- cgit v1.2.3 From 24c5100aceedcd47af89aaa404d4c96cd2837523 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 4 Jun 2024 10:41:39 +0300 Subject: fs/ntfs3: Fix getting file type An additional condition causes the mft record to be read from disk and get the file type dt_type. Fixes: 22457c047ed97 ("fs/ntfs3: Modified fix directory element type detection") Signed-off-by: Konstantin Komarov --- fs/ntfs3/dir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c index 1937e8e612f8..858efe255f6f 100644 --- a/fs/ntfs3/dir.c +++ b/fs/ntfs3/dir.c @@ -326,7 +326,8 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, * It does additional locks/reads just to get the type of name. * Should we use additional mount option to enable branch below? */ - if ((fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT) && + if (((fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT) || + fname->dup.ea_size) && ino != ni->mi.rno) { struct inode *inode = ntfs_iget5(sbi->sb, &e->ref, NULL); if (!IS_ERR_OR_NULL(inode)) { -- cgit v1.2.3 From bc81e773fec1bf83852b3bc6f6ad25125bf26416 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 09:57:12 +0300 Subject: fs/ntfs3: Remove sync_blockdev_nowait() Flush the file mapping directly. Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 2a7348b7a167..aca697f6b428 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1093,7 +1093,7 @@ 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; } -- cgit v1.2.3 From 0f9579d9e0331b6255132ac06bdf2c0a01cceb90 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 09:58:13 +0300 Subject: fs/ntfs3: Add missing .dirty_folio in address_space_operations After switching from pages to folio [1], it became evident that the initialization of .dirty_folio for page cache operations was missed for compressed files. [1] https://lore.kernel.org/ntfs3/20240422193203.3534108-1-willy@infradead.org Fixes: 82cae269cfa95 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index aca697f6b428..e9a83a937a02 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -2131,5 +2131,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 -- cgit v1.2.3 From 519f38de57cd0c5e0043795b5fb0686c97311f6d Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 May 2024 10:44:17 +0300 Subject: fs/ntfs3: Fix attr_insert_range at end of file If the offset is equal to or greater than the end of file, an error is returned. For such operations (i.e., inserting a hole at the end of file), ftruncate(2) should be used. Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 0d13da5523b1..68d1c61fe3b5 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2373,8 +2373,13 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) mask = (sbi->cluster_size << attr_b->nres.c_unit) - 1; } - if (vbo > data_size) { - /* Insert range after the file size is not allowed. */ + if (vbo >= data_size) { + /* + * Insert range after the file size is not allowed. + * If the offset is equal to or greater than the end of + * file, an error is returned. For such operations (i.e., inserting + * a hole at the end of file), ftruncate(2) should be used. + */ return -EINVAL; } -- cgit v1.2.3 From 69505fe98f198ee813898cbcaf6770949636430b Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 May 2024 10:54:07 +0300 Subject: fs/ntfs3: Replace inode_trylock with inode_lock The issue was detected due to xfstest 465 failing. Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 2f903b6ce157..9ae202901f3c 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -299,10 +299,7 @@ static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma) } if (ni->i_valid < to) { - if (!inode_trylock(inode)) { - err = -EAGAIN; - goto out; - } + inode_lock(inode); err = ntfs_extend_initialized_size(file, ni, ni->i_valid, to); inode_unlock(inode); -- cgit v1.2.3 From a0dde5d7a58b6bf9184ef3d8c6e62275c3645584 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 May 2024 10:55:12 +0300 Subject: fs/ntfs3: One more reason to mark inode bad In addition to returning an error, mark the node as bad. Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 4822cfd6351c..c7ab8d6f3896 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1601,8 +1601,10 @@ int ni_delete_all(struct ntfs_inode *ni) asize = le32_to_cpu(attr->size); roff = le16_to_cpu(attr->nres.run_off); - if (roff > asize) + if (roff > asize) { + _ntfs_bad_inode(&ni->vfs_inode); return -EINVAL; + } /* run==1 means unpack and deallocate. */ run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn, -- cgit v1.2.3 From f28d0866d8ff798aa497971f93d0cc58f442d946 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 May 2024 10:59:13 +0300 Subject: fs/ntfs3: Correct undo if ntfs_create_inode failed Clusters allocated for Extended Attributes, must be freed when rolling back inode creation. Fixes: 82cae269cfa95 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index e9a83a937a02..46130cbd08d4 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1666,7 +1666,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. @@ -1710,6 +1712,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); -- cgit v1.2.3 From 50c47879650b4c97836a0086632b3a2e300b0f06 Mon Sep 17 00:00:00 2001 From: lei lu Date: Wed, 29 May 2024 02:52:22 +0800 Subject: fs/ntfs3: Validate ff offset This adds sanity checks for ff offset. There is a check on rt->first_free at first, but walking through by ff without any check. If the second ff is a large offset. We may encounter an out-of-bound read. Signed-off-by: lei lu Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 763644f90094..6c18dc6c4cec 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -724,7 +724,8 @@ static bool check_rstbl(const struct RESTART_TABLE *rt, size_t bytes) if (!rsize || rsize > bytes || rsize + sizeof(struct RESTART_TABLE) > bytes || bytes < ts || - le16_to_cpu(rt->total) > ne || ff > ts || lf > ts || + le16_to_cpu(rt->total) > ne || + ff > ts - sizeof(__le32) || lf > ts - sizeof(__le32) || (ff && ff < sizeof(struct RESTART_TABLE)) || (lf && lf < sizeof(struct RESTART_TABLE))) { return false; @@ -754,6 +755,9 @@ static bool check_rstbl(const struct RESTART_TABLE *rt, size_t bytes) return false; off = le32_to_cpu(*(__le32 *)Add2Ptr(rt, off)); + + if (off > ts - sizeof(__le32)) + return false; } return true; -- cgit v1.2.3 From 702d4930eb06dcfda85a2fa67e8a1a27bfa2a845 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 13:13:17 +0300 Subject: fs/ntfs3: Add a check for attr_names and oatbl Added out-of-bound checking for *ane (ATTR_NAME_ENTRY). Reported-by: lei lu Fixes: 865e7a7700d93 ("fs/ntfs3: Reduce stack usage") Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 6c18dc6c4cec..e47c2105a24e 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -3726,6 +3726,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) u64 rec_lsn, checkpt_lsn = 0, rlsn = 0; struct ATTR_NAME_ENTRY *attr_names = NULL; + u32 attr_names_bytes = 0; + u32 oatbl_bytes = 0; struct RESTART_TABLE *dptbl = NULL; struct RESTART_TABLE *trtbl = NULL; const struct RESTART_TABLE *rt; @@ -3740,6 +3742,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) struct NTFS_RESTART *rst = NULL; struct lcb *lcb = NULL; struct OPEN_ATTR_ENRTY *oe; + struct ATTR_NAME_ENTRY *ane; struct TRANSACTION_ENTRY *tr; struct DIR_PAGE_ENTRY *dp; u32 i, bytes_per_attr_entry; @@ -4318,17 +4321,40 @@ check_attr_table: lcb = NULL; check_attribute_names2: - if (rst->attr_names_len && oatbl) { - struct ATTR_NAME_ENTRY *ane = attr_names; - while (ane->off) { + if (attr_names && oatbl) { + off = 0; + for (;;) { + /* Check we can use attribute name entry 'ane'. */ + static_assert(sizeof(*ane) == 4); + if (off + sizeof(*ane) > attr_names_bytes) { + /* just ignore the rest. */ + break; + } + + ane = Add2Ptr(attr_names, off); + t16 = le16_to_cpu(ane->off); + if (!t16) { + /* this is the only valid exit. */ + break; + } + + /* Check we can use open attribute entry 'oe'. */ + if (t16 + sizeof(*oe) > oatbl_bytes) { + /* just ignore the rest. */ + break; + } + /* TODO: Clear table on exit! */ - oe = Add2Ptr(oatbl, le16_to_cpu(ane->off)); + oe = Add2Ptr(oatbl, t16); t16 = le16_to_cpu(ane->name_bytes); + off += t16 + sizeof(*ane); + if (off > attr_names_bytes) { + /* just ignore the rest. */ + break; + } oe->name_len = t16 / sizeof(short); oe->ptr = ane->name; oe->is_attr_name = 2; - ane = Add2Ptr(ane, - sizeof(struct ATTR_NAME_ENTRY) + t16); } } -- cgit v1.2.3 From 83cf2cf18cbb97bfe87ea6a58f91df20e82ff38c Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 14:39:15 +0300 Subject: fs/ntfs3: Rename variables New names make it easier to read code. Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index e47c2105a24e..3d8d6f9b7883 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -4247,9 +4247,9 @@ check_attribute_names: } t32 = lrh_length(lrh); - rec_len -= t32; + attr_names_bytes = rec_len - t32; - attr_names = kmemdup(Add2Ptr(lrh, t32), rec_len, GFP_NOFS); + attr_names = kmemdup(Add2Ptr(lrh, t32), attr_names_bytes, GFP_NOFS); if (!attr_names) { err = -ENOMEM; goto out; @@ -4281,14 +4281,14 @@ check_attr_table: t16 = le16_to_cpu(lrh->redo_off); rt = Add2Ptr(lrh, t16); - t32 = rec_len - t16; + oatbl_bytes = rec_len - t16; - if (!check_rstbl(rt, t32)) { + if (!check_rstbl(rt, oatbl_bytes)) { err = -EINVAL; goto out; } - oatbl = kmemdup(rt, t32, GFP_NOFS); + oatbl = kmemdup(rt, oatbl_bytes, GFP_NOFS); if (!oatbl) { err = -ENOMEM; goto out; -- cgit v1.2.3 From ea7376783a9688dc9b66461080bfe0ae65e0d13d Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 3 Jun 2024 14:07:04 +0300 Subject: fs/ntfs3: Add some comments Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 14 ++++++-------- fs/ntfs3/inode.c | 4 ++-- fs/ntfs3/super.c | 5 ++--- 3 files changed, 10 insertions(+), 13 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 3d8d6f9b7883..f8da043be169 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -4111,7 +4111,7 @@ process_log: /* Allocate and Read the Transaction Table. */ if (!rst->transact_table_len) - goto check_dirty_page_table; + goto check_dirty_page_table; /* reduce tab pressure. */ t64 = le64_to_cpu(rst->transact_table_lsn); err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb); @@ -4151,7 +4151,7 @@ process_log: check_dirty_page_table: /* The next record back should be the Dirty Pages Table. */ if (!rst->dirty_pages_len) - goto check_attribute_names; + goto check_attribute_names; /* reduce tab pressure. */ t64 = le64_to_cpu(rst->dirty_pages_table_lsn); err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb); @@ -4187,7 +4187,7 @@ check_dirty_page_table: /* Convert Ra version '0' into version '1'. */ if (rst->major_ver) - goto end_conv_1; + goto end_conv_1; /* reduce tab pressure. */ dp = NULL; while ((dp = enum_rstbl(dptbl, dp))) { @@ -4207,8 +4207,7 @@ end_conv_1: * remembering the oldest lsn values. */ if (sbi->cluster_size <= log->page_size) - goto trace_dp_table; - + goto trace_dp_table; /* reduce tab pressure. */ dp = NULL; while ((dp = enum_rstbl(dptbl, dp))) { struct DIR_PAGE_ENTRY *next = dp; @@ -4229,7 +4228,7 @@ trace_dp_table: check_attribute_names: /* The next record should be the Attribute Names. */ if (!rst->attr_names_len) - goto check_attr_table; + goto check_attr_table; /* reduce tab pressure. */ t64 = le64_to_cpu(rst->attr_names_lsn); err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb); @@ -4261,7 +4260,7 @@ check_attribute_names: check_attr_table: /* The next record should be the attribute Table. */ if (!rst->open_attr_len) - goto check_attribute_names2; + goto check_attribute_names2; /* reduce tab pressure. */ t64 = le64_to_cpu(rst->open_attr_table_lsn); err = read_log_rec_lcb(log, t64, lcb_ctx_prev, &lcb); @@ -4550,7 +4549,6 @@ copy_lcns: } } goto next_log_record_analyze; - ; } case OpenNonresidentAttribute: diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 46130cbd08d4..374b10e5a6b7 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, @@ -1557,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; diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 6c9e5fe8ce81..e70ba2370c6e 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1205,7 +1205,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* * Load $Volume. This should be done before $LogFile - * 'cause 'sbi->volume.ni' is used 'ntfs_set_state'. + * 'cause 'sbi->volume.ni' is used in 'ntfs_set_state'. */ ref.low = cpu_to_le32(MFT_REC_VOL); ref.seq = cpu_to_le16(MFT_REC_VOL); @@ -1866,8 +1866,7 @@ static int __init init_ntfs_fs(void) ntfs_inode_cachep = kmem_cache_create( "ntfs_inode_cache", sizeof(struct ntfs_inode), 0, - (SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT), - init_once); + (SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT), init_once); if (!ntfs_inode_cachep) { err = -ENOMEM; goto out1; -- cgit v1.2.3 From b366809dd151e8abb29decda02fd6a78b498831f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 24 Apr 2024 00:01:01 +0300 Subject: fs/ntfs3: Drop stray '\' (backslash) in formatting string CHECK /home/andy/prj/linux-topic-uart/fs/ntfs3/super.c fs/ntfs3/super.c:471:23: warning: unknown escape sequence: '\%' Drop stray '\' (backslash) in formatting string. Fixes: d27e202b9ac4 ("fs/ntfs3: Add more info into /proc/fs/ntfs3//volinfo") Signed-off-by: Andy Shevchenko Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index e70ba2370c6e..5af07ced25ed 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -468,7 +468,7 @@ static int ntfs3_volinfo(struct seq_file *m, void *o) struct super_block *sb = m->private; struct ntfs_sb_info *sbi = sb->s_fs_info; - seq_printf(m, "ntfs%d.%d\n%u\n%zu\n\%zu\n%zu\n%s\n%s\n", + seq_printf(m, "ntfs%d.%d\n%u\n%zu\n%zu\n%zu\n%s\n%s\n", sbi->volume.major_ver, sbi->volume.minor_ver, sbi->cluster_size, sbi->used.bitmap.nbits, sbi->mft.bitmap.nbits, -- cgit v1.2.3 From f27a8e2d3dfcede23782b1cae1ae4ca4bda4e8ef Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:51 +0100 Subject: ntfs3: Convert ntfs_read_folio to use a folio Remove the struct page conversion, and use a folio throughout. We still convert back to a struct page for calling some internal functions, but those will change soon. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 374b10e5a6b7..baa81c95cc02 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -710,25 +710,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->page); 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->page); ni_unlock(ni); return err; } -- cgit v1.2.3 From 00c91073a34e81be35e01cf71ba15b5952006ccb Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:52 +0100 Subject: ntfs3: Convert ntfs_write_begin to use a folio Retrieve a folio from the page cache instead of a precise page. This function is now large folio safe, but its called function is not. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index baa81c95cc02..7288787b7ff2 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -913,24 +913,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->page); 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; -- cgit v1.2.3 From ab055cf9db2027f7cb59c80663578c053fb0afde Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:53 +0100 Subject: ntfs3: Convert attr_data_read_resident() to take a folio Now that all three callers have a folio, pass it in and use folio_fill_tail() to do the hard work of filling the folio. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 27 +++++++++------------------ fs/ntfs3/inode.c | 6 +++--- fs/ntfs3/ntfs_fs.h | 2 +- 3 files changed, 13 insertions(+), 22 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 68d1c61fe3b5..73c22c518697 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1239,11 +1239,12 @@ undo1: goto out; } -int attr_data_read_resident(struct ntfs_inode *ni, struct page *page) +int attr_data_read_resident(struct ntfs_inode *ni, struct folio *folio) { u64 vbo; struct ATTRIB *attr; u32 data_size; + size_t len; attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, NULL); if (!attr) @@ -1252,25 +1253,15 @@ int attr_data_read_resident(struct ntfs_inode *ni, struct page *page) if (attr->non_res) return E_NTFS_NONRESIDENT; - vbo = page->index << PAGE_SHIFT; + vbo = folio->index << PAGE_SHIFT; data_size = le32_to_cpu(attr->res.data_size); - if (vbo < data_size) { - const char *data = resident_data(attr); - char *kaddr = kmap_atomic(page); - u32 use = data_size - vbo; - - if (use > PAGE_SIZE) - use = PAGE_SIZE; + if (vbo > data_size) + len = 0; + else + len = min(data_size - vbo, folio_size(folio)); - memcpy(kaddr, data + vbo, use); - memset(kaddr + use, 0, PAGE_SIZE - use); - kunmap_atomic(kaddr); - flush_dcache_page(page); - SetPageUptodate(page); - } else if (!PageUptodate(page)) { - zero_user_segment(page, 0, PAGE_SIZE); - SetPageUptodate(page); - } + folio_fill_tail(folio, 0, resident_data(attr) + vbo, len); + folio_mark_uptodate(folio); return 0; } diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 7288787b7ff2..fd544e710ed1 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -583,7 +583,7 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, 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) @@ -717,7 +717,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio) if (is_resident(ni)) { ni_lock(ni); - err = attr_data_read_resident(ni, &folio->page); + err = attr_data_read_resident(ni, folio); ni_unlock(ni); if (err != E_NTFS_NONRESIDENT) { folio_unlock(folio); @@ -923,7 +923,7 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping, } ni_lock(ni); - err = attr_data_read_resident(ni, &folio->page); + err = attr_data_read_resident(ni, folio); ni_unlock(ni); if (!err) { diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 3583d47b95da..d2feb3de6502 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -434,7 +434,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, struct ATTRIB **ret); int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, CLST *len, bool *new, bool zero); -int attr_data_read_resident(struct ntfs_inode *ni, struct page *page); +int attr_data_read_resident(struct ntfs_inode *ni, struct folio *folio); int attr_data_write_resident(struct ntfs_inode *ni, struct page *page); int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name, u8 name_len, struct runs_tree *run, -- cgit v1.2.3 From 0c1a1566447ebeccaa3694e04ae65c7642fa783e Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:54 +0100 Subject: ntfs3: Convert ntfs_write_end() to work on a folio Convert the passed page back into a folio and use the folio APIs, saving a few hidden calls to compound_head(). Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index fd544e710ed1..e51454ae4dc3 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -950,6 +950,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; @@ -961,23 +962,23 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, err = attr_data_write_resident(ni, page); 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); -- cgit v1.2.3 From d0c3df62779f875b9af953790e5e18bce2aed91e Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:55 +0100 Subject: ntfs3: Convert attr_data_write_resident to use a folio Now that both callers of attr_data_write_resident() have a folio, pass it in and use memcpy_from_folio() to handle all the gnarly highmem multi-page problems. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 12 ++++-------- fs/ntfs3/inode.c | 4 ++-- fs/ntfs3/ntfs_fs.h | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 73c22c518697..1292fc84f092 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1266,7 +1266,7 @@ int attr_data_read_resident(struct ntfs_inode *ni, struct folio *folio) return 0; } -int attr_data_write_resident(struct ntfs_inode *ni, struct page *page) +int attr_data_write_resident(struct ntfs_inode *ni, struct folio *folio) { u64 vbo; struct mft_inode *mi; @@ -1282,17 +1282,13 @@ int attr_data_write_resident(struct ntfs_inode *ni, struct page *page) return E_NTFS_NONRESIDENT; } - vbo = page->index << PAGE_SHIFT; + vbo = folio->index << PAGE_SHIFT; data_size = le32_to_cpu(attr->res.data_size); if (vbo < data_size) { char *data = resident_data(attr); - char *kaddr = kmap_atomic(page); - u32 use = data_size - vbo; + size_t len = min(data_size - vbo, folio_size(folio)); - if (use > PAGE_SIZE) - use = PAGE_SIZE; - memcpy(data + vbo, kaddr, use); - kunmap_atomic(kaddr); + memcpy_from_folio(data + vbo, folio, 0, len); mi->dirty = true; } ni->i_valid = data_size; diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index e51454ae4dc3..74f6c7e567e7 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -871,7 +871,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) @@ -959,7 +959,7 @@ 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); diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index d2feb3de6502..7ad02f2dde2a 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -435,7 +435,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, CLST *len, bool *new, bool zero); int attr_data_read_resident(struct ntfs_inode *ni, struct folio *folio); -int attr_data_write_resident(struct ntfs_inode *ni, struct page *page); +int attr_data_write_resident(struct ntfs_inode *ni, struct folio *folio); int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name, u8 name_len, struct runs_tree *run, CLST vcn); -- cgit v1.2.3 From 562d060bed6637fbc3bc22802a0a0c5b00e12a38 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:56 +0100 Subject: ntfs3: Convert attr_make_nonresident to use a folio Fetch a folio from the page cache instead of a page and operate on it. Signed-off-by: Matthew Wilcox (Oracle) [almaz.alexandrovich@paragon-software.com: skip using folio_end_read] Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 1292fc84f092..3a4b81bbc5d9 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -288,22 +288,21 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr, if (err) goto out2; } else if (!page) { - char *kaddr; - - page = grab_cache_page(ni->vfs_inode.i_mapping, 0); - if (!page) { - err = -ENOMEM; + struct address_space *mapping = ni->vfs_inode.i_mapping; + struct folio *folio; + + folio = __filemap_get_folio(mapping, 0, + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, + mapping_gfp_mask(mapping)); + if (IS_ERR(folio)) { + err = PTR_ERR(folio); goto out2; } - kaddr = kmap_atomic(page); - memcpy(kaddr, data, rsize); - memset(kaddr + rsize, 0, PAGE_SIZE - rsize); - kunmap_atomic(kaddr); - flush_dcache_page(page); - SetPageUptodate(page); - set_page_dirty(page); - unlock_page(page); - put_page(page); + folio_fill_tail(folio, 0, data, rsize); + folio_mark_uptodate(folio); + folio_mark_dirty(folio); + folio_unlock(folio); + folio_put(folio); } } -- cgit v1.2.3 From 326a6fd9600c52016c3c18c1aeafca2fab254146 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:58 +0100 Subject: ntfs3: Remove calls to set/clear the error flag Nobody checks the error flag on ntfs3 folios, so stop setting and clearing it. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index c7ab8d6f3896..de9ef8c211ed 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -2145,9 +2145,6 @@ int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page) err = ni_read_frame(ni, frame_vbo, pages, pages_per_frame); out1: - if (err) - SetPageError(page); - for (i = 0; i < pages_per_frame; i++) { pg = pages[i]; if (i == idx || !pg) @@ -2720,7 +2717,6 @@ out: for (i = 0; i < pages_per_frame; i++) { pg = pages[i]; kunmap(pg); - ClearPageError(pg); SetPageUptodate(pg); } -- cgit v1.2.3 From 584f60ba22f79c89e6708ab82a5b5d9b8fa21fb2 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:32:00 +0100 Subject: ntfs3: Convert ntfs_get_frame_pages() to use a folio The function still takes an array of pages, but use a folio internally. This function would deadlock against itself if used with large folios (as it locks each page), so we can be a little sloppy with the conversion back from folio to page for now. Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 9ae202901f3c..35ca0f201cb8 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -821,23 +821,24 @@ static int ntfs_get_frame_pages(struct address_space *mapping, pgoff_t index, *frame_uptodate = true; for (npages = 0; npages < pages_per_frame; npages++, index++) { - struct page *page; + struct folio *folio; - page = find_or_create_page(mapping, index, gfp_mask); - if (!page) { + folio = __filemap_get_folio(mapping, index, + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp_mask); + if (IS_ERR(folio)) { while (npages--) { - page = pages[npages]; - unlock_page(page); - put_page(page); + folio = page_folio(pages[npages]); + folio_unlock(folio); + folio_put(folio); } return -ENOMEM; } - if (!PageUptodate(page)) + if (!folio_test_uptodate(folio)) *frame_uptodate = false; - pages[npages] = page; + pages[npages] = &folio->page; } return 0; -- cgit v1.2.3 From 4d89b6716b00bf52e2c4f98d5d7788d300469a5f Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:32:01 +0100 Subject: ntfs3: Convert ni_readpage_cmpr() to take a folio We still use an array of pages for the decompression, but this removes a few calls to compound_head(). Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 13 +++++++------ fs/ntfs3/inode.c | 2 +- fs/ntfs3/ntfs_fs.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index de9ef8c211ed..7962471692e6 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -2087,12 +2087,12 @@ out: * When decompressing, we typically obtain more than one page per reference. * We inject the additional pages into the page cache. */ -int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page) +int ni_readpage_cmpr(struct ntfs_inode *ni, struct folio *folio) { int err; struct ntfs_sb_info *sbi = ni->mi.sbi; - struct address_space *mapping = page->mapping; - pgoff_t index = page->index; + struct address_space *mapping = folio->mapping; + pgoff_t index = folio->index; u64 frame_vbo, vbo = (u64)index << PAGE_SHIFT; struct page **pages = NULL; /* Array of at most 16 pages. stack? */ u8 frame_bits; @@ -2102,7 +2102,8 @@ int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page) struct page *pg; if (vbo >= i_size_read(&ni->vfs_inode)) { - SetPageUptodate(page); + folio_zero_range(folio, 0, folio_size(folio)); + folio_mark_uptodate(folio); err = 0; goto out; } @@ -2126,7 +2127,7 @@ int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page) goto out; } - pages[idx] = page; + pages[idx] = &folio->page; index = frame_vbo >> PAGE_SHIFT; gfp_mask = mapping_gfp_mask(mapping); @@ -2156,7 +2157,7 @@ out1: out: /* At this point, err contains 0 or -EIO depending on the "critical" page. */ kfree(pages); - unlock_page(page); + folio_unlock(folio); return err; } diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 74f6c7e567e7..68dd71eed3fe 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -727,7 +727,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio) if (is_compressed(ni)) { ni_lock(ni); - err = ni_readpage_cmpr(ni, &folio->page); + err = ni_readpage_cmpr(ni, folio); ni_unlock(ni); return err; } diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 7ad02f2dde2a..e2a3ecc12247 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -564,7 +564,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint); #define _ni_write_inode(i, w) ni_write_inode(i, w, __func__) int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, __u64 vbo, __u64 len); -int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page); +int ni_readpage_cmpr(struct ntfs_inode *ni, struct folio *folio); int ni_decompress_file(struct ntfs_inode *ni); int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages, u32 pages_per_frame); -- cgit v1.2.3 From c091354d6bf60ec606d4c0772459ea2f3bbee271 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 22 Apr 2024 20:31:59 +0100 Subject: ntfs3: Convert attr_wof_frame_info() to use a folio This involves converting all users of offs_page to offs_folio, but it's worth it because we get rid of a lot of hidden calls to compound_head(). We continue to use order-0 folios here, and convert back to a struct page to call ntfs_bio_pages(). Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 27 ++++++++++++++------------- fs/ntfs3/frecord.c | 12 ++++++------ fs/ntfs3/ntfs_fs.h | 2 +- 3 files changed, 21 insertions(+), 20 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 3a4b81bbc5d9..e62a8fee5250 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1380,7 +1380,7 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, u32 voff; u8 bytes_per_off; char *addr; - struct page *page; + struct folio *folio; int i, err; __le32 *off32; __le64 *off64; @@ -1425,18 +1425,18 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, wof_size = le64_to_cpu(attr->nres.data_size); down_write(&ni->file.run_lock); - page = ni->file.offs_page; - if (!page) { - page = alloc_page(GFP_KERNEL); - if (!page) { + folio = ni->file.offs_folio; + if (!folio) { + folio = folio_alloc(GFP_KERNEL, 0); + if (!folio) { err = -ENOMEM; goto out; } - page->index = -1; - ni->file.offs_page = page; + folio->index = -1; + ni->file.offs_folio = folio; } - lock_page(page); - addr = page_address(page); + folio_lock(folio); + addr = folio_address(folio); if (vbo[1]) { voff = vbo[1] & (PAGE_SIZE - 1); @@ -1452,7 +1452,8 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, do { pgoff_t index = vbo[i] >> PAGE_SHIFT; - if (index != page->index) { + if (index != folio->index) { + struct page *page = &folio->page; u64 from = vbo[i] & ~(u64)(PAGE_SIZE - 1); u64 to = min(from + PAGE_SIZE, wof_size); @@ -1465,10 +1466,10 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, err = ntfs_bio_pages(sbi, run, &page, 1, from, to - from, REQ_OP_READ); if (err) { - page->index = -1; + folio->index = -1; goto out1; } - page->index = index; + folio->index = index; } if (i) { @@ -1506,7 +1507,7 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, *ondisk_size = off[1] - off[0]; out1: - unlock_page(page); + folio_unlock(folio); out: up_write(&ni->file.run_lock); return err; diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 7962471692e6..d792908c85f4 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -122,10 +122,10 @@ void ni_clear(struct ntfs_inode *ni) else { run_close(&ni->file.run); #ifdef CONFIG_NTFS3_LZX_XPRESS - if (ni->file.offs_page) { + if (ni->file.offs_folio) { /* On-demand allocated page for offsets. */ - put_page(ni->file.offs_page); - ni->file.offs_page = NULL; + folio_put(ni->file.offs_folio); + ni->file.offs_folio = NULL; } #endif } @@ -2362,9 +2362,9 @@ remove_wof: /* Clear cached flag. */ ni->ni_flags &= ~NI_FLAG_COMPRESSED_MASK; - if (ni->file.offs_page) { - put_page(ni->file.offs_page); - ni->file.offs_page = NULL; + if (ni->file.offs_folio) { + folio_put(ni->file.offs_folio); + ni->file.offs_folio = NULL; } mapping->a_ops = &ntfs_aops; diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index e2a3ecc12247..8074fc53a145 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -383,7 +383,7 @@ struct ntfs_inode { struct rw_semaphore run_lock; struct runs_tree run; #ifdef CONFIG_NTFS3_LZX_XPRESS - struct page *offs_page; + struct folio *offs_folio; #endif } file; }; -- cgit v1.2.3 From 2f3e176fee66ac86ae387787bf06457b101d9f7a Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 17 Jun 2024 15:13:09 +0300 Subject: fs/ntfs3: Fix field-spanning write in INDEX_HDR Fields flags and res[3] replaced with one 4 byte flags. Fixes: 4534a70b7056 ("fs/ntfs3: Add headers and misc files") Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 4 ++-- fs/ntfs3/ntfs.h | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index d0f15bbf78f6..9089c58a005c 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -978,7 +978,7 @@ static struct indx_node *indx_new(struct ntfs_index *indx, hdr->used = cpu_to_le32(eo + sizeof(struct NTFS_DE) + sizeof(u64)); de_set_vbn_le(e, *sub_vbn); - hdr->flags = 1; + hdr->flags = NTFS_INDEX_HDR_HAS_SUBNODES; } else { e->size = cpu_to_le16(sizeof(struct NTFS_DE)); hdr->used = cpu_to_le32(eo + sizeof(struct NTFS_DE)); @@ -1683,7 +1683,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, e->size = cpu_to_le16(sizeof(struct NTFS_DE) + sizeof(u64)); e->flags = NTFS_IE_HAS_SUBNODES | NTFS_IE_LAST; - hdr->flags = 1; + hdr->flags = NTFS_INDEX_HDR_HAS_SUBNODES; hdr->used = hdr->total = cpu_to_le32(new_root_size - offsetof(struct INDEX_ROOT, ihdr)); diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index a5ca08db6dc5..241f2ffdd920 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h @@ -693,14 +693,15 @@ static inline bool de_has_vcn_ex(const struct NTFS_DE *e) offsetof(struct ATTR_FILE_NAME, name) + \ NTFS_NAME_LEN * sizeof(short), 8) +#define NTFS_INDEX_HDR_HAS_SUBNODES cpu_to_le32(1) + struct INDEX_HDR { __le32 de_off; // 0x00: The offset from the start of this structure // to the first NTFS_DE. __le32 used; // 0x04: The size of this structure plus all // entries (quad-word aligned). __le32 total; // 0x08: The allocated size of for this structure plus all entries. - u8 flags; // 0x0C: 0x00 = Small directory, 0x01 = Large directory. - u8 res[3]; + __le32 flags; // 0x0C: 0x00 = Small directory, 0x01 = Large directory. // // de_off + used <= total @@ -748,7 +749,7 @@ static inline struct NTFS_DE *hdr_next_de(const struct INDEX_HDR *hdr, static inline bool hdr_has_subnode(const struct INDEX_HDR *hdr) { - return hdr->flags & 1; + return hdr->flags & NTFS_INDEX_HDR_HAS_SUBNODES; } struct INDEX_BUFFER { @@ -768,7 +769,7 @@ static inline bool ib_is_empty(const struct INDEX_BUFFER *ib) static inline bool ib_is_leaf(const struct INDEX_BUFFER *ib) { - return !(ib->ihdr.flags & 1); + return !(ib->ihdr.flags & NTFS_INDEX_HDR_HAS_SUBNODES); } /* Index root structure ( 0x90 ). */ -- cgit v1.2.3 From d392e85fd1e8d58e460c17ca7d0d5c157848d9c1 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 25 Jun 2024 09:57:33 +0300 Subject: fs/ntfs3: Fix the format of the "nocase" mount option The 'nocase' option was mistakenly added as fsparam_flag_no with the 'no' prefix, causing the case-insensitive mode to require the 'nonocase' option to be enabled. Fixes: a3a956c78efa ("fs/ntfs3: Add option "nocase"") Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 5af07ced25ed..c39a70b93bb1 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -275,7 +275,7 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("acl", Opt_acl), fsparam_string("iocharset", Opt_iocharset), fsparam_flag_no("prealloc", Opt_prealloc), - fsparam_flag_no("nocase", Opt_nocase), + fsparam_flag_no("case", Opt_nocase), {} }; // clang-format on -- cgit v1.2.3 From 2cbbd96820255fff4f0ad1533197370c9ccc570b Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 17 Jun 2024 13:43:09 +0300 Subject: fs/ntfs3: Missed error return Fixes: 3f3b442b5ad2 ("fs/ntfs3: Add bitmap") Signed-off-by: Konstantin Komarov --- fs/ntfs3/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ntfs3') diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c index c9eb01ccee51..cf4fe21a5039 100644 --- a/fs/ntfs3/bitmap.c +++ b/fs/ntfs3/bitmap.c @@ -1382,7 +1382,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits) err = ntfs_vbo_to_lbo(sbi, &wnd->run, vbo, &lbo, &bytes); if (err) - break; + return err; bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits); if (!bh) -- cgit v1.2.3 From eb95678ee930d67d79fc83f0a700245ae7230455 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 18 Jun 2024 17:11:37 +0300 Subject: fs/ntfs3: Keep runs for $MFT::$AT