lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Thu, 7 Jul 2022 19:36:35 +0300
From:   Konstantin Komarov <almaz.alexandrovich@...agon-software.com>
To:     <ntfs3@...ts.linux.dev>
CC:     <linux-kernel@...r.kernel.org>, <linux-fsdevel@...r.kernel.org>
Subject: [PATCH] fs/ntfs3: Make MFT zone less fragmented

Now we take free space after the MFT zone if the MFT zone shrinks.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@...agon-software.com>
---
  fs/ntfs3/fsntfs.c  | 39 +++++++++++++++++++++++++--------------
  fs/ntfs3/ntfs_fs.h |  1 +
  fs/ntfs3/super.c   |  7 +++++++
  3 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
index c53dd4c9e47b..ed9a1b851ce9 100644
--- a/fs/ntfs3/fsntfs.c
+++ b/fs/ntfs3/fsntfs.c
@@ -783,7 +783,7 @@ int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to)
   */
  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;
@@ -1398,7 +1388,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);
@@ -2427,7 +2417,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);
@@ -2462,6 +2452,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);
  }
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index cf1fa69a0eb8..54c20700afd3 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -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.
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index eacea72ff92f..6fad173a8b8f 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -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:
-- 
2.37.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ