fs/ntfs3: Make MFT zone less fragmented
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Thu, 7 Jul 2022 16:25:43 +0000 (19:25 +0300)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Wed, 3 Aug 2022 15:25:08 +0000 (18:25 +0300)
Now we take free space after the MFT zone if the MFT zone shrinks.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/fsntfs.c
fs/ntfs3/ntfs_fs.h
fs/ntfs3/super.c

index fa4ca8b..af1dca2 100644 (file)
@@ -783,7 +783,7 @@ out:
  */
 int ntfs_refresh_zone(struct ntfs_sb_info *sbi)
 {
-       CLST zone_limit, zone_max, lcn, vcn, len;
+       CLST lcn, vcn, len;
        size_t lcn_s, zlen;
        struct wnd_bitmap *wnd = &sbi->used.bitmap;
        struct ntfs_inode *ni = sbi->mft.ni;
@@ -792,16 +792,6 @@ int ntfs_refresh_zone(struct ntfs_sb_info *sbi)
        if (wnd_zone_len(wnd))
                return 0;
 
-       /*
-        * Compute the MFT zone at two steps.
-        * It would be nice if we are able to allocate 1/8 of
-        * total clusters for MFT but not more then 512 MB.
-        */
-       zone_limit = (512 * 1024 * 1024) >> sbi->cluster_bits;
-       zone_max = wnd->nbits >> 3;
-       if (zone_max > zone_limit)
-               zone_max = zone_limit;
-
        vcn = bytes_to_cluster(sbi,
                               (u64)sbi->mft.bitmap.nbits << sbi->record_bits);
 
@@ -815,7 +805,7 @@ int ntfs_refresh_zone(struct ntfs_sb_info *sbi)
        lcn_s = lcn + 1;
 
        /* Try to allocate clusters after last MFT run. */
-       zlen = wnd_find(wnd, zone_max, lcn_s, 0, &lcn_s);
+       zlen = wnd_find(wnd, sbi->zone_max, lcn_s, 0, &lcn_s);
        if (!zlen) {
                ntfs_notice(sbi->sb, "MftZone: unavailable");
                return 0;
@@ -1397,7 +1387,7 @@ int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr,
                if (buffer_locked(bh))
                        __wait_on_buffer(bh);
 
-               lock_buffer(nb->bh[idx]);
+               lock_buffer(bh);
 
                bh_data = bh->b_data + off;
                end_data = Add2Ptr(bh_data, op);
@@ -2426,7 +2416,7 @@ static inline void ntfs_unmap_and_discard(struct ntfs_sb_info *sbi, CLST lcn,
 
 void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim)
 {
-       CLST end, i;
+       CLST end, i, zone_len, zlen;
        struct wnd_bitmap *wnd = &sbi->used.bitmap;
 
        down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
@@ -2461,6 +2451,27 @@ void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim)
                ntfs_unmap_and_discard(sbi, lcn, len);
        wnd_set_free(wnd, lcn, len);
 
+       /* append to MFT zone, if possible. */
+       zone_len = wnd_zone_len(wnd);
+       zlen = min(zone_len + len, sbi->zone_max);
+
+       if (zlen == zone_len) {
+               /* MFT zone already has maximum size. */
+       } else if (!zone_len) {
+               /* Create MFT zone. */
+               wnd_zone_set(wnd, lcn, zlen);
+       } else {
+               CLST zone_lcn = wnd_zone_bit(wnd);
+
+               if (lcn + len == zone_lcn) {
+                       /* Append into head MFT zone. */
+                       wnd_zone_set(wnd, lcn, zlen);
+               } else if (zone_lcn + zone_len == lcn) {
+                       /* Append into tail MFT zone. */
+                       wnd_zone_set(wnd, zone_lcn, zlen);
+               }
+       }
+
 out:
        up_write(&wnd->rw_lock);
 }
index 7a728d3..6a2bbf8 100644 (file)
@@ -220,6 +220,7 @@ struct ntfs_sb_info {
 
        u32 flags; // See NTFS_FLAGS_XXX.
 
+       CLST zone_max; // Maximum MFT zone length in clusters
        CLST bad_clusters; // The count of marked bad clusters.
 
        u16 max_bytes_per_attr; // Maximum attribute size in record.
index eacea72..6fad173 100644 (file)
@@ -867,6 +867,13 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
        sb->s_maxbytes = 0xFFFFFFFFull << sbi->cluster_bits;
 #endif
 
+       /*
+        * Compute the MFT zone at two steps.
+        * It would be nice if we are able to allocate 1/8 of
+        * total clusters for MFT but not more then 512 MB.
+        */
+       sbi->zone_max = min_t(CLST, 0x20000000 >> sbi->cluster_bits, clusters >> 3);
+
        err = 0;
 
 out: