Skip to content

Commit

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

Pull ntfs3 updates from Konstantin Komarov:

 - additional checks to address issues identified by syzbot

 - continuation of the transition from 'page' to 'folio'

* tag 'ntfs3_for_6.13' of https://github.com/Paragon-Software-Group/linux-ntfs3:
  fs/ntfs3: Accumulated refactoring changes
  fs/ntfs3: Switch to folio to release resources
  fs/ntfs3: Add check in ntfs_extend_initialized_size
  fs/ntfs3: Add more checks in mi_enum_attr (part 2)
  fs/ntfs3: Equivalent transition from page to folio
  fs/ntfs3: Fix case when unmarked clusters intersect with zone
  fs/ntfs3: Fix warning in ni_fiemap
  • Loading branch information
torvalds committed Nov 28, 2024
2 parents 8170a99 + bac89bb commit 1fdae00
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 167 deletions.
9 changes: 4 additions & 5 deletions fs/ntfs3/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,

/* Check for compressed frame. */
err = attr_is_frame_compressed(ni, attr_b, vcn >> NTFS_LZNT_CUNIT,
&hint);
&hint, run);
if (err)
goto out;

Expand Down Expand Up @@ -1521,16 +1521,16 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
* attr_is_frame_compressed - Used to detect compressed frame.
*
* attr - base (primary) attribute segment.
* run - run to use, usually == &ni->file.run.
* Only base segments contains valid 'attr->nres.c_unit'
*/
int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
CLST frame, CLST *clst_data)
CLST frame, CLST *clst_data, struct runs_tree *run)
{
int err;
u32 clst_frame;
CLST clen, lcn, vcn, alen, slen, vcn_next;
size_t idx;
struct runs_tree *run;

*clst_data = 0;

Expand All @@ -1542,7 +1542,6 @@ int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,

clst_frame = 1u << attr->nres.c_unit;
vcn = frame * clst_frame;
run = &ni->file.run;

if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
err = attr_load_runs_vcn(ni, attr->type, attr_name(attr),
Expand Down Expand Up @@ -1678,7 +1677,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
if (err)
goto out;

err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data);
err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data, run);
if (err)
goto out;

Expand Down
62 changes: 17 additions & 45 deletions fs/ntfs3/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,20 +710,17 @@ int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits)
{
int err = 0;
struct super_block *sb = wnd->sb;
size_t bits0 = bits;
u32 wbits = 8 * sb->s_blocksize;
size_t iw = bit >> (sb->s_blocksize_bits + 3);
u32 wbit = bit & (wbits - 1);
struct buffer_head *bh;
u32 op;

while (iw < wnd->nwnd && bits) {
u32 tail, op;

for (; iw < wnd->nwnd && bits; iw++, bit += op, bits -= op, wbit = 0) {
if (iw + 1 == wnd->nwnd)
wbits = wnd->bits_last;

tail = wbits - wbit;
op = min_t(u32, tail, bits);
op = min_t(u32, wbits - wbit, bits);

bh = wnd_map(wnd, iw);
if (IS_ERR(bh)) {
Expand All @@ -736,20 +733,15 @@ int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits)
ntfs_bitmap_clear_le(bh->b_data, wbit, op);

wnd->free_bits[iw] += op;
wnd->total_zeroes += op;

set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
unlock_buffer(bh);
put_bh(bh);

wnd->total_zeroes += op;
bits -= op;
wbit = 0;
iw += 1;
wnd_add_free_ext(wnd, bit, op, false);
}

wnd_add_free_ext(wnd, bit, bits0, false);

return err;
}

Expand All @@ -760,20 +752,17 @@ int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
{
int err = 0;
struct super_block *sb = wnd->sb;
size_t bits0 = bits;
size_t iw = bit >> (sb->s_blocksize_bits + 3);
u32 wbits = 8 * sb->s_blocksize;
u32 wbit = bit & (wbits - 1);
struct buffer_head *bh;
u32 op;

while (iw < wnd->nwnd && bits) {
u32 tail, op;

for (; iw < wnd->nwnd && bits; iw++, bit += op, bits -= op, wbit = 0) {
if (unlikely(iw + 1 == wnd->nwnd))
wbits = wnd->bits_last;

tail = wbits - wbit;
op = min_t(u32, tail, bits);
op = min_t(u32, wbits - wbit, bits);

bh = wnd_map(wnd, iw);
if (IS_ERR(bh)) {
Expand All @@ -785,21 +774,16 @@ int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)

ntfs_bitmap_set_le(bh->b_data, wbit, op);
wnd->free_bits[iw] -= op;
wnd->total_zeroes -= op;

set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
unlock_buffer(bh);
put_bh(bh);

wnd->total_zeroes -= op;
bits -= op;
wbit = 0;
iw += 1;
if (!RB_EMPTY_ROOT(&wnd->start_tree))
wnd_remove_free_ext(wnd, bit, op);
}

if (!RB_EMPTY_ROOT(&wnd->start_tree))
wnd_remove_free_ext(wnd, bit, bits0);

return err;
}

Expand Down Expand Up @@ -852,15 +836,13 @@ static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits)
size_t iw = bit >> (sb->s_blocksize_bits + 3);
u32 wbits = 8 * sb->s_blocksize;
u32 wbit = bit & (wbits - 1);
u32 op;

while (iw < wnd->nwnd && bits) {
u32 tail, op;

for (; iw < wnd->nwnd && bits; iw++, bits -= op, wbit = 0) {
if (unlikely(iw + 1 == wnd->nwnd))
wbits = wnd->bits_last;

tail = wbits - wbit;
op = min_t(u32, tail, bits);
op = min_t(u32, wbits - wbit, bits);

if (wbits != wnd->free_bits[iw]) {
bool ret;
Expand All @@ -875,10 +857,6 @@ static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits)
if (!ret)
return false;
}

bits -= op;
wbit = 0;
iw += 1;
}

return true;
Expand Down Expand Up @@ -928,6 +906,7 @@ bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
size_t iw = bit >> (sb->s_blocksize_bits + 3);
u32 wbits = 8 * sb->s_blocksize;
u32 wbit = bit & (wbits - 1);
u32 op;
size_t end;
struct rb_node *n;
struct e_node *e;
Expand All @@ -945,14 +924,11 @@ bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
return false;

use_wnd:
while (iw < wnd->nwnd && bits) {
u32 tail, op;

for (; iw < wnd->nwnd && bits; iw++, bits -= op, wbit = 0) {
if (unlikely(iw + 1 == wnd->nwnd))
wbits = wnd->bits_last;

tail = wbits - wbit;
op = min_t(u32, tail, bits);
op = min_t(u32, wbits - wbit, bits);

if (wnd->free_bits[iw]) {
bool ret;
Expand All @@ -966,10 +942,6 @@ bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
if (!ret)
goto out;
}

bits -= op;
wbit = 0;
iw += 1;
}
ret = true;

Expand Down
34 changes: 21 additions & 13 deletions fs/ntfs3/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,15 @@ static int ntfs_extend_initialized_size(struct file *file,
loff_t pos = valid;
int err;

if (valid >= new_valid)
return 0;

if (is_resident(ni)) {
ni->i_valid = new_valid;
return 0;
}

WARN_ON(is_compressed(ni));
WARN_ON(valid >= new_valid);

for (;;) {
u32 zerofrom, len;
Expand Down Expand Up @@ -222,7 +224,7 @@ static int ntfs_extend_initialized_size(struct file *file,
if (err)
goto out;

folio_zero_range(folio, zerofrom, folio_size(folio));
folio_zero_range(folio, zerofrom, folio_size(folio) - zerofrom);

err = ntfs_write_end(file, mapping, pos, len, len, folio, NULL);
if (err < 0)
Expand Down Expand Up @@ -987,6 +989,7 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
u64 frame_vbo;
pgoff_t index;
bool frame_uptodate;
struct folio *folio;

if (frame_size < PAGE_SIZE) {
/*
Expand Down Expand Up @@ -1041,8 +1044,9 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
if (err) {
for (ip = 0; ip < pages_per_frame; ip++) {
page = pages[ip];
unlock_page(page);
put_page(page);
folio = page_folio(page);
folio_unlock(folio);
folio_put(folio);
}
goto out;
}
Expand All @@ -1052,9 +1056,10 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
off = offset_in_page(valid);
for (; ip < pages_per_frame; ip++, off = 0) {
page = pages[ip];
folio = page_folio(page);
zero_user_segment(page, off, PAGE_SIZE);
flush_dcache_page(page);
SetPageUptodate(page);
folio_mark_uptodate(folio);
}

ni_lock(ni);
Expand All @@ -1063,9 +1068,10 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)

for (ip = 0; ip < pages_per_frame; ip++) {
page = pages[ip];
SetPageUptodate(page);
unlock_page(page);
put_page(page);
folio = page_folio(page);
folio_mark_uptodate(folio);
folio_unlock(folio);
folio_put(folio);
}

if (err)
Expand Down Expand Up @@ -1107,8 +1113,9 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
for (ip = 0; ip < pages_per_frame;
ip++) {
page = pages[ip];
unlock_page(page);
put_page(page);
folio = page_folio(page);
folio_unlock(folio);
folio_put(folio);
}
goto out;
}
Expand Down Expand Up @@ -1149,9 +1156,10 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
for (ip = 0; ip < pages_per_frame; ip++) {
page = pages[ip];
ClearPageDirty(page);
SetPageUptodate(page);
unlock_page(page);
put_page(page);
folio = page_folio(page);
folio_mark_uptodate(folio);
folio_unlock(folio);
folio_put(folio);
}

if (err)
Expand Down
Loading

0 comments on commit 1fdae00

Please sign in to comment.