Skip to content

Commit 3b06a27

Browse files
committed
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 ...
2 parents ae2a823 + d407359 commit 3b06a27

File tree

14 files changed

+835
-329
lines changed

14 files changed

+835
-329
lines changed

fs/ntfs3/attrib.c

Lines changed: 464 additions & 93 deletions
Large diffs are not rendered by default.

fs/ntfs3/bitmap.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ void ntfs3_exit_bitmap(void)
5151
kmem_cache_destroy(ntfs_enode_cachep);
5252
}
5353

54-
static inline u32 wnd_bits(const struct wnd_bitmap *wnd, size_t i)
55-
{
56-
return i + 1 == wnd->nwnd ? wnd->bits_last : wnd->sb->s_blocksize * 8;
57-
}
58-
5954
/*
6055
* wnd_scan
6156
*
@@ -1333,9 +1328,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
13331328
if (!new_free)
13341329
return -ENOMEM;
13351330

1336-
if (new_free != wnd->free_bits)
1337-
memcpy(new_free, wnd->free_bits,
1338-
wnd->nwnd * sizeof(short));
1331+
memcpy(new_free, wnd->free_bits, wnd->nwnd * sizeof(short));
13391332
memset(new_free + wnd->nwnd, 0,
13401333
(new_wnd - wnd->nwnd) * sizeof(short));
13411334
kfree(wnd->free_bits);
@@ -1395,9 +1388,8 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
13951388

13961389
void wnd_zone_set(struct wnd_bitmap *wnd, size_t lcn, size_t len)
13971390
{
1398-
size_t zlen;
1391+
size_t zlen = wnd->zone_end - wnd->zone_bit;
13991392

1400-
zlen = wnd->zone_end - wnd->zone_bit;
14011393
if (zlen)
14021394
wnd_add_free_ext(wnd, wnd->zone_bit, zlen, false);
14031395

fs/ntfs3/file.c

Lines changed: 66 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -530,21 +530,35 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size)
530530
static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
531531
{
532532
struct inode *inode = file->f_mapping->host;
533+
struct address_space *mapping = inode->i_mapping;
533534
struct super_block *sb = inode->i_sb;
534535
struct ntfs_sb_info *sbi = sb->s_fs_info;
535536
struct ntfs_inode *ni = ntfs_i(inode);
536537
loff_t end = vbo + len;
537538
loff_t vbo_down = round_down(vbo, PAGE_SIZE);
538-
loff_t i_size;
539+
bool is_supported_holes = is_sparsed(ni) || is_compressed(ni);
540+
loff_t i_size, new_size;
541+
bool map_locked;
539542
int err;
540543

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

545-
/* Return error if mode is not supported. */
546-
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
547-
FALLOC_FL_COLLAPSE_RANGE)) {
548+
/*
549+
* vfs_fallocate checks all possible combinations of mode.
550+
* Do additional checks here before ntfs_set_state(dirty).
551+
*/
552+
if (mode & FALLOC_FL_PUNCH_HOLE) {
553+
if (!is_supported_holes)
554+
return -EOPNOTSUPP;
555+
} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
556+
} else if (mode & FALLOC_FL_INSERT_RANGE) {
557+
if (!is_supported_holes)
558+
return -EOPNOTSUPP;
559+
} else if (mode &
560+
~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
561+
FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)) {
548562
ntfs_inode_warn(inode, "fallocate(0x%x) is not supported",
549563
mode);
550564
return -EOPNOTSUPP;
@@ -554,45 +568,36 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
554568

555569
inode_lock(inode);
556570
i_size = inode->i_size;
571+
new_size = max(end, i_size);
572+
map_locked = false;
557573

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

580+
if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
581+
FALLOC_FL_INSERT_RANGE)) {
582+
inode_dio_wait(inode);
583+
filemap_invalidate_lock(mapping);
584+
map_locked = true;
585+
}
586+
564587
if (mode & FALLOC_FL_PUNCH_HOLE) {
565588
u32 frame_size;
566589
loff_t mask, vbo_a, end_a, tmp;
567590

568-
if (!(mode & FALLOC_FL_KEEP_SIZE)) {
569-
err = -EINVAL;
570-
goto out;
571-
}
572-
573-
err = filemap_write_and_wait_range(inode->i_mapping, vbo,
574-
end - 1);
591+
err = filemap_write_and_wait_range(mapping, vbo, end - 1);
575592
if (err)
576593
goto out;
577594

578-
err = filemap_write_and_wait_range(inode->i_mapping, end,
579-
LLONG_MAX);
595+
err = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
580596
if (err)
581597
goto out;
582598

583-
inode_dio_wait(inode);
584-
585599
truncate_pagecache(inode, vbo_down);
586600

587-
if (!is_sparsed(ni) && !is_compressed(ni)) {
588-
/*
589-
* Normal file, can't make hole.
590-
* TODO: Try to find way to save info about hole.
591-
*/
592-
err = -EOPNOTSUPP;
593-
goto out;
594-
}
595-
596601
ni_lock(ni);
597602
err = attr_punch_hole(ni, vbo, len, &frame_size);
598603
ni_unlock(ni);
@@ -624,52 +629,70 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
624629
ni_unlock(ni);
625630
}
626631
} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
627-
if (mode & ~FALLOC_FL_COLLAPSE_RANGE) {
628-
err = -EINVAL;
629-
goto out;
630-
}
631-
632632
/*
633633
* Write tail of the last page before removed range since
634634
* it will get removed from the page cache below.
635635
*/
636-
err = filemap_write_and_wait_range(inode->i_mapping, vbo_down,
637-
vbo);
636+
err = filemap_write_and_wait_range(mapping, vbo_down, vbo);
638637
if (err)
639638
goto out;
640639

641640
/*
642641
* Write data that will be shifted to preserve them
643642
* when discarding page cache below.
644643
*/
645-
err = filemap_write_and_wait_range(inode->i_mapping, end,
646-
LLONG_MAX);
644+
err = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
647645
if (err)
648646
goto out;
649647

650-
/* Wait for existing dio to complete. */
651-
inode_dio_wait(inode);
652-
653648
truncate_pagecache(inode, vbo_down);
654649

655650
ni_lock(ni);
656651
err = attr_collapse_range(ni, vbo, len);
657652
ni_unlock(ni);
653+
} else if (mode & FALLOC_FL_INSERT_RANGE) {
654+
/* Check new size. */
655+
err = inode_newsize_ok(inode, new_size);
656+
if (err)
657+
goto out;
658+
659+
/* Write out all dirty pages. */
660+
err = filemap_write_and_wait_range(mapping, vbo_down,
661+
LLONG_MAX);
662+
if (err)
663+
goto out;
664+
truncate_pagecache(inode, vbo_down);
665+
666+
ni_lock(ni);
667+
err = attr_insert_range(ni, vbo, len);
668+
ni_unlock(ni);
658669
} else {
659-
/*
660-
* Normal file: Allocate clusters, do not change 'valid' size.
661-
*/
662-
loff_t new_size = max(end, i_size);
670+
/* Check new size. */
671+
672+
/* generic/213: expected -ENOSPC instead of -EFBIG. */
673+
if (!is_supported_holes) {
674+
loff_t to_alloc = new_size - inode_get_bytes(inode);
675+
676+
if (to_alloc > 0 &&
677+
(to_alloc >> sbi->cluster_bits) >
678+
wnd_zeroes(&sbi->used.bitmap)) {
679+
err = -ENOSPC;
680+
goto out;
681+
}
682+
}
663683

664684
err = inode_newsize_ok(inode, new_size);
665685
if (err)
666686
goto out;
667687

688+
/*
689+
* Allocate clusters, do not change 'valid' size.
690+
*/
668691
err = ntfs_set_size(inode, new_size);
669692
if (err)
670693
goto out;
671694

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

719742
out:
720-
if (err == -EFBIG)
721-
err = -ENOSPC;
743+
if (map_locked)
744+
filemap_invalidate_unlock(mapping);
722745

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

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

0 commit comments

Comments
 (0)