]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fs/ntfs3: Optimize large writes into sparse file
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Fri, 28 Jun 2024 15:27:46 +0000 (18:27 +0300)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Tue, 3 Sep 2024 13:58:39 +0000 (16:58 +0300)
Optimized cluster allocation by allocating a large chunk in advance
before writing, instead of allocating during the writing process
by clusters.
Essentially replicates the logic of fallocate.

Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation")
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/file.c

index cddc51f9a93b2355b207b2a1aa3fd945a52d7a0f..d31eae611fe066edeaf2f0e93c6b634cccd02814 100644 (file)
@@ -408,6 +408,42 @@ static int ntfs_extend(struct inode *inode, loff_t pos, size_t count,
                err = 0;
        }
 
+       if (file && is_sparsed(ni)) {
+               /*
+                * This code optimizes large writes to sparse file.
+                * TODO: merge this fragment with fallocate fragment.
+                */
+               struct ntfs_sb_info *sbi = ni->mi.sbi;
+               CLST vcn = pos >> sbi->cluster_bits;
+               CLST cend = bytes_to_cluster(sbi, end);
+               CLST cend_v = bytes_to_cluster(sbi, ni->i_valid);
+               CLST lcn, clen;
+               bool new;
+
+               if (cend_v > cend)
+                       cend_v = cend;
+
+               /*
+                * Allocate and zero new clusters.
+                * Zeroing these clusters may be too long.
+                */
+               for (; vcn < cend_v; vcn += clen) {
+                       err = attr_data_get_block(ni, vcn, cend_v - vcn, &lcn,
+                                                 &clen, &new, true);
+                       if (err)
+                               goto out;
+               }
+               /*
+                * Allocate but not zero new clusters.
+                */
+               for (; vcn < cend; vcn += clen) {
+                       err = attr_data_get_block(ni, vcn, cend - vcn, &lcn,
+                                                 &clen, &new, false);
+                       if (err)
+                               goto out;
+               }
+       }
+
        inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
        mark_inode_dirty(inode);