Skip to content

Commit ecbb433

Browse files
fs/ntfs3: fold file size handling into ntfs_set_size()
Remove the separate ntfs_extend() and ntfs_truncate() helpers and route file size changes through ntfs_set_size(). This consolidates ntfs3 size updates in one place and lets the write, fallocate, and setattr paths share the same logic for updating i_size, valid data length, and preallocated extents. This patch fixes a few issues found during internal tests. Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
1 parent 9245b4a commit ecbb433

2 files changed

Lines changed: 51 additions & 148 deletions

File tree

fs/ntfs3/file.c

Lines changed: 40 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -450,93 +450,6 @@ static int ntfs_file_mmap_prepare(struct vm_area_desc *desc)
450450
return err;
451451
}
452452

453-
static int ntfs_extend(struct inode *inode, loff_t pos, size_t count,
454-
struct file *file)
455-
{
456-
struct ntfs_inode *ni = ntfs_i(inode);
457-
struct address_space *mapping = inode->i_mapping;
458-
loff_t end = pos + count;
459-
bool extend_init = file && pos > ni->i_valid;
460-
int err;
461-
462-
if (end <= inode->i_size && !extend_init)
463-
return 0;
464-
465-
/* Mark rw ntfs as dirty. It will be cleared at umount. */
466-
ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_DIRTY);
467-
468-
if (end > inode->i_size) {
469-
/*
470-
* Normal files: increase file size, allocate space.
471-
* Sparse/Compressed: increase file size. No space allocated.
472-
*/
473-
err = ntfs_set_size(inode, end);
474-
if (err)
475-
goto out;
476-
}
477-
478-
if (extend_init && !is_compressed(ni)) {
479-
err = ntfs_extend_initialized_size(file, ni, pos);
480-
if (err)
481-
goto out;
482-
} else {
483-
err = 0;
484-
}
485-
486-
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
487-
mark_inode_dirty(inode);
488-
489-
if (IS_SYNC(inode)) {
490-
int err2;
491-
492-
err = filemap_fdatawrite_range(mapping, pos, end - 1);
493-
err2 = write_inode_now(inode, 1);
494-
if (!err)
495-
err = err2;
496-
if (!err)
497-
err = filemap_fdatawait_range(mapping, pos, end - 1);
498-
}
499-
500-
out:
501-
return err;
502-
}
503-
504-
static int ntfs_truncate(struct inode *inode, loff_t new_size)
505-
{
506-
int err;
507-
struct ntfs_inode *ni = ntfs_i(inode);
508-
u64 new_valid = min_t(u64, ni->i_valid, new_size);
509-
510-
truncate_setsize(inode, new_size);
511-
512-
ni_lock(ni);
513-
514-
down_write(&ni->file.run_lock);
515-
err = attr_set_size_ex(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size,
516-
&new_valid, ni->mi.sbi->options->prealloc, NULL,
517-
false);
518-
up_write(&ni->file.run_lock);
519-
520-
ni->i_valid = new_valid;
521-
522-
ni_unlock(ni);
523-
524-
if (err)
525-
return err;
526-
527-
ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE;
528-
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
529-
if (!IS_DIRSYNC(inode)) {
530-
mark_inode_dirty(inode);
531-
} else {
532-
err = ntfs_sync_inode(inode);
533-
if (err)
534-
return err;
535-
}
536-
537-
return 0;
538-
}
539-
540453
/*
541454
* ntfs_fallocate - file_operations::ntfs_fallocate
542455
*
@@ -743,57 +656,25 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
743656
if (is_supported_holes) {
744657
CLST vcn = vbo >> cluster_bits;
745658
CLST cend = bytes_to_cluster(sbi, end);
746-
CLST cend_v = bytes_to_cluster(sbi, ni->i_valid);
747659
CLST lcn, clen;
748660
bool new;
749661

750-
if (cend_v > cend)
751-
cend_v = cend;
752-
753662
/*
754663
* Allocate and zero new clusters.
755-
* Zeroing these clusters may be too long.
756-
*/
757-
for (; vcn < cend_v; vcn += clen) {
758-
err = attr_data_get_block(ni, vcn, cend_v - vcn,
759-
&lcn, &clen, &new,
760-
true, NULL, false);
761-
if (err)
762-
goto out;
763-
}
764-
765-
/*
766-
* Moving up 'valid size'.
767-
*/
768-
err = ntfs_extend_initialized_size(
769-
file, ni, (u64)cend_v << cluster_bits);
770-
if (err)
771-
goto out;
772-
773-
/*
774-
* Allocate but not zero new clusters.
775664
*/
776665
for (; vcn < cend; vcn += clen) {
777666
err = attr_data_get_block(ni, vcn, cend - vcn,
778667
&lcn, &clen, &new,
779-
false, NULL, false);
668+
true, NULL, false);
780669
if (err)
781670
goto out;
782671
}
783672
}
784673

785674
if (mode & FALLOC_FL_KEEP_SIZE) {
786-
ni_lock(ni);
787-
/* True - Keep preallocated. */
788-
err = attr_set_size(ni, ATTR_DATA, NULL, 0,
789-
&ni->file.run, i_size, &ni->i_valid,
790-
true);
791-
ni_unlock(ni);
675+
err = ntfs_set_size(inode, i_size);
792676
if (err)
793677
goto out;
794-
i_size_write(inode, i_size);
795-
} else if (new_size > i_size) {
796-
i_size_write(inode, new_size);
797678
}
798679
}
799680

@@ -850,16 +731,20 @@ int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
850731
oldsize = i_size_read(inode);
851732
newsize = attr->ia_size;
852733

853-
if (newsize <= oldsize)
854-
err = ntfs_truncate(inode, newsize);
855-
else
856-
err = ntfs_extend(inode, newsize, 0, NULL);
734+
if (newsize != oldsize) {
735+
truncate_setsize(inode, newsize);
857736

858-
if (err)
859-
goto out;
737+
err = ntfs_set_size(inode, newsize);
738+
if (err) {
739+
i_size_write(inode, oldsize);
740+
goto out;
741+
}
860742

861-
ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
862-
i_size_write(inode, newsize);
743+
ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE;
744+
ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
745+
inode_set_mtime_to_ts(inode,
746+
inode_set_ctime_current(inode));
747+
}
863748
}
864749

865750
setattr_copy(idmap, inode, attr);
@@ -1333,6 +1218,7 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
13331218
struct file *file = iocb->ki_filp;
13341219
struct inode *inode = file_inode(file);
13351220
struct ntfs_inode *ni = ntfs_i(inode);
1221+
loff_t vbo, endbyte;
13361222
ssize_t ret, err;
13371223

13381224
if (!inode_trylock(inode)) {
@@ -1367,15 +1253,30 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
13671253
goto out;
13681254
}
13691255

1370-
ret = ntfs_extend(inode, iocb->ki_pos, ret, file);
1371-
if (ret)
1372-
goto out;
1256+
vbo = iocb->ki_pos;
1257+
endbyte = vbo + ret;
1258+
1259+
if (endbyte > inode->i_size) {
1260+
/*
1261+
* Normal files: increase file size, allocate space.
1262+
* Sparse/Compressed: increase file size. No space allocated.
1263+
*/
1264+
ret = ntfs_set_size(inode, endbyte);
1265+
if (ret)
1266+
goto out;
1267+
}
13731268

13741269
if (is_compressed(ni)) {
13751270
ret = ntfs_compress_write(iocb, from);
13761271
goto out;
13771272
}
13781273

1274+
if (vbo > ni->i_valid) {
1275+
ret = ntfs_extend_initialized_size(file, ni, vbo);
1276+
if (ret)
1277+
goto out;
1278+
}
1279+
13791280
/* Fallback to buffered I/O if the inode does not support direct I/O. */
13801281
if (!(iocb->ki_flags & IOCB_DIRECT) ||
13811282
!ntfs_should_use_dio(iocb, from)) {
@@ -1408,7 +1309,7 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
14081309
}
14091310

14101311
if (ret >= 0 && iov_iter_count(from)) {
1411-
loff_t offset = iocb->ki_pos, endbyte;
1312+
vbo = iocb->ki_pos;
14121313

14131314
iocb->ki_flags &= ~IOCB_DIRECT;
14141315
err = iomap_file_buffered_write(iocb, from, &ntfs_iomap_ops,
@@ -1426,15 +1327,15 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
14261327
* to complete off the I/O request.
14271328
*/
14281329
ret += err;
1429-
endbyte = offset + err - 1;
1430-
err = filemap_write_and_wait_range(inode->i_mapping, offset,
1330+
endbyte = vbo + err - 1;
1331+
err = filemap_write_and_wait_range(inode->i_mapping, vbo,
14311332
endbyte);
14321333
if (err) {
14331334
ret = err;
14341335
goto out;
14351336
}
14361337

1437-
invalidate_mapping_pages(inode->i_mapping, offset >> PAGE_SHIFT,
1338+
invalidate_mapping_pages(inode->i_mapping, vbo >> PAGE_SHIFT,
14381339
endbyte >> PAGE_SHIFT);
14391340
}
14401341

@@ -1515,8 +1416,9 @@ static int ntfs_file_release(struct inode *inode, struct file *file)
15151416
down_write(&ni->file.run_lock);
15161417

15171418
/* Deallocate preallocated. */
1518-
err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run,
1519-
inode->i_size, &ni->i_valid, false);
1419+
err = attr_set_size_ex(ni, ATTR_DATA, NULL, 0, &ni->file.run,
1420+
inode->i_size, &ni->i_valid, false, NULL,
1421+
true);
15201422

15211423
up_write(&ni->file.run_lock);
15221424
ni_unlock(ni);

fs/ntfs3/inode.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -693,17 +693,18 @@ int ntfs_set_size(struct inode *inode, u64 new_size)
693693
return -EFBIG;
694694
}
695695

696+
/* Mark rw ntfs as dirty. It will be cleared at umount. */
697+
ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
698+
696699
ni_lock(ni);
697700
down_write(&ni->file.run_lock);
701+
if (new_size < ni->i_valid)
702+
ni->i_valid = new_size;
698703

704+
/* last 'true' means keep preallocated. */
699705
err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size,
700706
&ni->i_valid, true);
701707

702-
if (!err) {
703-
i_size_write(inode, new_size);
704-
mark_inode_dirty(inode);
705-
}
706-
707708
up_write(&ni->file.run_lock);
708709
ni_unlock(ni);
709710

@@ -778,11 +779,6 @@ static int ntfs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
778779
return err;
779780
}
780781

781-
if (!clen) {
782-
/* broken file? */
783-
return -EINVAL;
784-
}
785-
786782
if (lcn == EOF_LCN) {
787783
/* request out of file. */
788784
if (flags & IOMAP_REPORT) {
@@ -816,6 +812,11 @@ static int ntfs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
816812
return 0;
817813
}
818814

815+
if (!clen) {
816+
/* broken file? */
817+
return -EINVAL;
818+
}
819+
819820
iomap->bdev = inode->i_sb->s_bdev;
820821
iomap->offset = offset;
821822
iomap->length = ((loff_t)clen << cluster_bits) - off;

0 commit comments

Comments
 (0)