diff options
author | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2024-04-16 09:08:18 +0200 |
---|---|---|
committer | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2024-04-23 08:34:25 +0200 |
commit | 40bb3c590582f488ec1ff8c31b7fc806e5732f42 (patch) | |
tree | 8b49f2f8a7d89fd686bcf964c841c625dc18dbc1 /fs/ntfs3 | |
parent | fs/ntfs3: Redesign ntfs_create_inode to return error code instead of inode (diff) | |
download | linux-40bb3c590582f488ec1ff8c31b7fc806e5732f42.tar.xz linux-40bb3c590582f488ec1ff8c31b7fc806e5732f42.zip |
fs/ntfs3: Always make file nonresident on fallocate call
xfstest 438 is starting to pass with this change.
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Diffstat (limited to 'fs/ntfs3')
-rw-r--r-- | fs/ntfs3/attrib.c | 32 | ||||
-rw-r--r-- | fs/ntfs3/file.c | 9 | ||||
-rw-r--r-- | fs/ntfs3/ntfs_fs.h | 1 |
3 files changed, 42 insertions, 0 deletions
diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 7aadf5010999..8e6bcdf99770 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2558,3 +2558,35 @@ undo_insert_range: goto out; } + +/* + * attr_force_nonresident + * + * Convert default data attribute into non resident form. + */ +int attr_force_nonresident(struct ntfs_inode *ni) +{ + int err; + struct ATTRIB *attr; + struct ATTR_LIST_ENTRY *le = NULL; + struct mft_inode *mi; + + attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi); + if (!attr) { + ntfs_bad_inode(&ni->vfs_inode, "no data attribute"); + return -ENOENT; + } + + if (attr->non_res) { + /* Already non resident. */ + return 0; + } + + down_write(&ni->file.run_lock); + err = attr_make_nonresident(ni, attr, le, mi, + le32_to_cpu(attr->res.data_size), + &ni->file.run, &attr, NULL); + up_write(&ni->file.run_lock); + + return err; +} diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 5418662c80d8..fce8ea098d60 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -578,6 +578,15 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) /* Check new size. */ u8 cluster_bits = sbi->cluster_bits; + /* Be sure file is non resident. */ + if (is_resident(ni)) { + ni_lock(ni); + err = attr_force_nonresident(ni); + ni_unlock(ni); + if (err) + goto out; + } + /* generic/213: expected -ENOSPC instead of -EFBIG. */ if (!is_supported_holes) { loff_t to_alloc = new_size - inode_get_bytes(inode); diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 3db6a61f61dc..00dec0ec5648 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -452,6 +452,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes); int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes); int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size); +int attr_force_nonresident(struct ntfs_inode *ni); /* Functions from attrlist.c */ void al_destroy(struct ntfs_inode *ni); |