All of lore.kernel.org
 help / color / mirror / Atom feed
From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
To: <ntfs3@lists.linux.dev>
Cc: <linux-kernel@vger.kernel.org>, <linux-fsdevel@vger.kernel.org>
Subject: [PATCH] fs/ntfs3: Make MFT zone less fragmented
Date: Thu, 7 Jul 2022 19:36:35 +0300	[thread overview]
Message-ID: <24343399-2866-2a52-ef86-3b1722fc04cd@paragon-software.com> (raw)

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  | 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


                 reply	other threads:[~2022-07-07 16:36 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=24343399-2866-2a52-ef86-3b1722fc04cd@paragon-software.com \
    --to=almaz.alexandrovich@paragon-software.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ntfs3@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.