Skip to content

Commit

Permalink
Merge tag 'ntfs3_for_6.0' of https://github.com/Paragon-Software-Grou…
Browse files Browse the repository at this point in the history
…p/linux-ntfs3

Pull ntfs3 updates from Konstantin Komarov:

 - implement FALLOC_FL_INSERT_RANGE

 - fix some logic errors

 - fixed xfstests (tested on x86_64): generic/064 generic/213
   generic/300 generic/361 generic/449 generic/485

 - some dead code removed or refactored

* tag 'ntfs3_for_6.0' of https://github.com/Paragon-Software-Group/linux-ntfs3: (39 commits)
  fs/ntfs3: uninitialized variable in ntfs_set_acl_ex()
  fs/ntfs3: Remove unused function wnd_bits
  fs/ntfs3: Make ni_ins_new_attr return error
  fs/ntfs3: Create MFT zone only if length is large enough
  fs/ntfs3: Refactoring attr_insert_range to restore after errors
  fs/ntfs3: Refactoring attr_punch_hole to restore after errors
  fs/ntfs3: Refactoring attr_set_size to restore after errors
  fs/ntfs3: New function ntfs_bad_inode
  fs/ntfs3: Make MFT zone less fragmented
  fs/ntfs3: Check possible errors in run_pack in advance
  fs/ntfs3: Added comments to frecord functions
  fs/ntfs3: Fill duplicate info in ni_add_name
  fs/ntfs3: Make static function attr_load_runs
  fs/ntfs3: Add new argument is_mft to ntfs_mark_rec_free
  fs/ntfs3: Remove unused mi_mark_free
  fs/ntfs3: Fix very fragmented case in attr_punch_hole
  fs/ntfs3: Fix work with fragmented xattr
  fs/ntfs3: Make ntfs_fallocate return -ENOSPC instead of -EFBIG
  fs/ntfs3: extend ni_insert_nonresident to return inserted ATTR_LIST_ENTRY
  fs/ntfs3: Check reserved size for maximum allowed
  ...
  • Loading branch information
Linus Torvalds committed Aug 17, 2022
2 parents ae2a823 + d407359 commit 3b06a27
Show file tree
Hide file tree
Showing 14 changed files with 835 additions and 329 deletions.
557 changes: 464 additions & 93 deletions fs/ntfs3/attrib.c

Large diffs are not rendered by default.

12 changes: 2 additions & 10 deletions fs/ntfs3/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ void ntfs3_exit_bitmap(void)
kmem_cache_destroy(ntfs_enode_cachep);
}

static inline u32 wnd_bits(const struct wnd_bitmap *wnd, size_t i)
{
return i + 1 == wnd->nwnd ? wnd->bits_last : wnd->sb->s_blocksize * 8;
}

/*
* wnd_scan
*
Expand Down Expand Up @@ -1333,9 +1328,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
if (!new_free)
return -ENOMEM;

if (new_free != wnd->free_bits)
memcpy(new_free, wnd->free_bits,
wnd->nwnd * sizeof(short));
memcpy(new_free, wnd->free_bits, wnd->nwnd * sizeof(short));
memset(new_free + wnd->nwnd, 0,
(new_wnd - wnd->nwnd) * sizeof(short));
kfree(wnd->free_bits);
Expand Down Expand Up @@ -1395,9 +1388,8 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)

void wnd_zone_set(struct wnd_bitmap *wnd, size_t lcn, size_t len)
{
size_t zlen;
size_t zlen = wnd->zone_end - wnd->zone_bit;

zlen = wnd->zone_end - wnd->zone_bit;
if (zlen)
wnd_add_free_ext(wnd, wnd->zone_bit, zlen, false);

Expand Down
110 changes: 66 additions & 44 deletions fs/ntfs3/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,21 +530,35 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size)
static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
{
struct inode *inode = file->f_mapping->host;
struct address_space *mapping = inode->i_mapping;
struct super_block *sb = inode->i_sb;
struct ntfs_sb_info *sbi = sb->s_fs_info;
struct ntfs_inode *ni = ntfs_i(inode);
loff_t end = vbo + len;
loff_t vbo_down = round_down(vbo, PAGE_SIZE);
loff_t i_size;
bool is_supported_holes = is_sparsed(ni) || is_compressed(ni);
loff_t i_size, new_size;
bool map_locked;
int err;

/* No support for dir. */
if (!S_ISREG(inode->i_mode))
return -EOPNOTSUPP;

/* Return error if mode is not supported. */
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
FALLOC_FL_COLLAPSE_RANGE)) {
/*
* vfs_fallocate checks all possible combinations of mode.
* Do additional checks here before ntfs_set_state(dirty).
*/
if (mode & FALLOC_FL_PUNCH_HOLE) {
if (!is_supported_holes)
return -EOPNOTSUPP;
} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
} else if (mode & FALLOC_FL_INSERT_RANGE) {
if (!is_supported_holes)
return -EOPNOTSUPP;
} else if (mode &
~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)) {
ntfs_inode_warn(inode, "fallocate(0x%x) is not supported",
mode);
return -EOPNOTSUPP;
Expand All @@ -554,45 +568,36 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)

inode_lock(inode);
i_size = inode->i_size;
new_size = max(end, i_size);
map_locked = false;

if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {
/* Should never be here, see ntfs_file_open. */
err = -EOPNOTSUPP;
goto out;
}

if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
FALLOC_FL_INSERT_RANGE)) {
inode_dio_wait(inode);
filemap_invalidate_lock(mapping);
map_locked = true;
}

if (mode & FALLOC_FL_PUNCH_HOLE) {
u32 frame_size;
loff_t mask, vbo_a, end_a, tmp;

if (!(mode & FALLOC_FL_KEEP_SIZE)) {
err = -EINVAL;
goto out;
}

err = filemap_write_and_wait_range(inode->i_mapping, vbo,
end - 1);
err = filemap_write_and_wait_range(mapping, vbo, end - 1);
if (err)
goto out;

err = filemap_write_and_wait_range(inode->i_mapping, end,
LLONG_MAX);
err = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
if (err)
goto out;

inode_dio_wait(inode);

truncate_pagecache(inode, vbo_down);

if (!is_sparsed(ni) && !is_compressed(ni)) {
/*
* Normal file, can't make hole.
* TODO: Try to find way to save info about hole.
*/
err = -EOPNOTSUPP;
goto out;
}

ni_lock(ni);
err = attr_punch_hole(ni, vbo, len, &frame_size);
ni_unlock(ni);
Expand Down Expand Up @@ -624,52 +629,70 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
ni_unlock(ni);
}
} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
if (mode & ~FALLOC_FL_COLLAPSE_RANGE) {
err = -EINVAL;
goto out;
}

/*
* Write tail of the last page before removed range since
* it will get removed from the page cache below.
*/
err = filemap_write_and_wait_range(inode->i_mapping, vbo_down,
vbo);
err = filemap_write_and_wait_range(mapping, vbo_down, vbo);
if (err)
goto out;

/*
* Write data that will be shifted to preserve them
* when discarding page cache below.
*/
err = filemap_write_and_wait_range(inode->i_mapping, end,
LLONG_MAX);
err = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
if (err)
goto out;

/* Wait for existing dio to complete. */
inode_dio_wait(inode);

truncate_pagecache(inode, vbo_down);

ni_lock(ni);
err = attr_collapse_range(ni, vbo, len);
ni_unlock(ni);
} else if (mode & FALLOC_FL_INSERT_RANGE) {
/* Check new size. */
err = inode_newsize_ok(inode, new_size);
if (err)
goto out;

/* Write out all dirty pages. */
err = filemap_write_and_wait_range(mapping, vbo_down,
LLONG_MAX);
if (err)
goto out;
truncate_pagecache(inode, vbo_down);

ni_lock(ni);
err = attr_insert_range(ni, vbo, len);
ni_unlock(ni);
} else {
/*
* Normal file: Allocate clusters, do not change 'valid' size.
*/
loff_t new_size = max(end, i_size);
/* Check new size. */

/* generic/213: expected -ENOSPC instead of -EFBIG. */
if (!is_supported_holes) {
loff_t to_alloc = new_size - inode_get_bytes(inode);

if (to_alloc > 0 &&
(to_alloc >> sbi->cluster_bits) >
wnd_zeroes(&sbi->used.bitmap)) {
err = -ENOSPC;
goto out;
}
}

err = inode_newsize_ok(inode, new_size);
if (err)
goto out;

/*
* Allocate clusters, do not change 'valid' size.
*/
err = ntfs_set_size(inode, new_size);
if (err)
goto out;

if (is_sparsed(ni) || is_compressed(ni)) {
if (is_supported_holes) {
CLST vcn_v = ni->i_valid >> sbi->cluster_bits;
CLST vcn = vbo >> sbi->cluster_bits;
CLST cend = bytes_to_cluster(sbi, end);
Expand Down Expand Up @@ -717,8 +740,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
}

out:
if (err == -EFBIG)
err = -ENOSPC;
if (map_locked)
filemap_invalidate_unlock(mapping);

if (!err) {
inode->i_ctime = inode->i_mtime = current_time(inode);
Expand Down Expand Up @@ -989,7 +1012,6 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
if (bytes > count)
bytes = count;

frame = pos >> frame_bits;
frame_vbo = pos & ~(frame_size - 1);
index = frame_vbo >> PAGE_SHIFT;

Expand Down
Loading

0 comments on commit 3b06a27

Please sign in to comment.