From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D79D377AB7 for ; Sun, 23 Aug 2026 17:45:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787507160; cv=none; b=OhIgFg7P12zDPYcwNej+J278IOfOTnR2tD3aH+XGCRup0B/z2/mGeCtM7Xjn4kG0znSWpUQwgG6AHLLuZywuhLQwjNxWfXe6tFNFcUYR0RMe4fOnHOiYeJ1sxpQeFa2/ZG+HrK0/mIyoHXjouGup8wnx0pfPE/riLo3f8qKeiAE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787507160; c=relaxed/simple; bh=CFpVY/DuqWTvXRc0p5OeDTR1CT91WanPPf4asRW2wHQ=; h=Message-ID:Date:From:To:Cc:Subject:MIME-Version:Content-Type: Content-Disposition; b=eyVMsaIEIsOPyLv5MSixzUmlcfLIYSblKR0z5rDnSl46Sjps+MJD9EhHWvAdvMsM6cFUetMPeOWOY+XM12af2M387bubUAQdLj6K6tL/4fsjcD0l2TQ8RLsnx5kQA7frHSTo4/v7c4lQJCaDtTA4dssU4mh33DWRyIQ9MJHEUiA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=o95zIDxZ; arc=none smtp.client-ip=209.85.210.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="o95zIDxZ" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-84faf87d19dso2674478b3a.3 for ; Sun, 23 Aug 2026 10:45:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787507156; x=1788111956; darn=vger.kernel.org; h=content-disposition:content-type:mime-version:subject:cc:to:from :date:message-id:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Tc7zVEq3TX2D4Zx5mQTGVnBlcFdChQX5tNfVNH60DjQ=; b=o95zIDxZ/Cl04jSn7DDjLfQkU2OzdxhZCI/X0mT58dvB+j9aWF44cdmZIwFwjwY22g 3GmwKnX/eiMLFia1DjVczKf0gih6pymJxdwtcM3JVYJhSMNEoY/qzjbRIqfrlROTuy6b qQNNOacMiB5Y8cBlfN9LFXW9hqU7nJZReZk4C8uGpt2kdGd7kcUdQdayYs1fBblyHMFk HSqzaJ9LKsZY6smgWqqYBxfk+8bERKoBuv0MRnY3dxegrIEeIYkjgKIKTKSZGqLkJcGC +67J+LkQCavKXDT0yLDclUoAkP4r6o2sBvbH6ZOjpdFBtWh1hlhrgSRj2zXDuy0+uKIK 4Dag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787507156; x=1788111956; h=content-disposition:content-type:mime-version:subject:cc:to:from :date:message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Tc7zVEq3TX2D4Zx5mQTGVnBlcFdChQX5tNfVNH60DjQ=; b=AoBNVJzgozJ4FU67ZoURrsVUz1HGEb//vPtbEKPr/1JC+VChPgcWoYcE4H+NNpOTdm rKx3CsXRho2Kb6LXP17X8elJUuxmx9ySqafx9JD7b51GAGrA1qVUu5l7/lU+zlinWcKj 0f1dhg0NFQ0h06QosD6TTn5+J/z339ITSFo/Kue42+cjCOsPFfK5LLE5DCEnq80YYeGl gIMQ5eReSBR7U1Y+WISpT3sOCyAuV0zMuvLDvb/Nb9WmCQdtiTN0Lvk0oU4wW7fbE5A0 QL/jkUa90CK/Eg816trBZUvy4YTiw6FLNEFU0HiKqLAuvsKN39RoD166eoyfWa74GWQR t4kg== X-Forwarded-Encrypted: i=1; AHgh+RrBulfQki5333DlxJp8z6CILoogsNSixCKrkCaR+bER7RCp5i3Kfr1Icdo1f38pgKlO4TVNoY8LWv6hWS8=@vger.kernel.org X-Gm-Message-State: AFuF++lZ1U61bGjvo+z2XYfoNfuy0KCYWlIQsbUaDndndTjO3AstQ780 tlG770pqsakB64QnFcNGy7OYauim4gZ/7kN1NH6m629huy2ugMcNhJ46 X-Gm-Gg: AR+sD10C5U555A/zXcAJOkVv8YDGpHZT8oSI3Siz9x5ozX/tN+8MR17PcZi+RlSlcxO /2pOwmmOGuSvgUxhu0cifjx6etTee7+ga9NubbDMJQ5FjuBDwc7qGVeeU64cgDftq9OGO1DoyDJ vbwFmK5ifYTjZxjgKlTw7h1GnKa9XhBXgk/Y0I0Ob9qyB4UQG+imwwyA7C1/uNEkIHYb+Kd/3KJ EoObWu9dBh+1JRe/7qQZUAa3bSrZtSbjxxTRWElbGHSpwdXhFQWB0qqsYUbb0bScr2Rm1aR7DnO nYI1NBaPq1D6rF+73zuZTDa3jcUlwu6oU+WhhnLifQsagcr6UDk8bkDAaQCDlce7ByF8fwaaBhq UPp/3xUw+Pk3RnlQbJ3ehyxADeJNEN3l5BjMj2NIL+3OAhUPYgX4e1tLX1QbwN28zJvdKsiVFr3 bxjlS8SsnG7fsEoX3rCElmf7qneSLed1vuOAVs5B3PkNP8VqHZ2veX767WHUw+495xzXizJKwmc e55LS+Ml5xsWyCLz/KLV71aHlmR58Mg9f7pgqUjDQhiNBftHzyVNO/P X-Received: by 2002:a05:6a20:9149:b0:3c6:61b9:917c with SMTP id adf61e73a8af0-3cd4bb97247mr22516717637.11.1787507156011; Sun, 23 Aug 2026 10:45:56 -0700 (PDT) Received: from localhost (75-172-9-230.tukw.qwest.net. [75.172.9.230]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-327f909c6c9sm20991252eec.6.2026.08.23.10.45.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 10:45:55 -0700 (PDT) Message-ID: <6a8b31d3.6dfd78af.244576.33c7@mx.google.com> X-Google-Original-Message-ID: Date: Sun, 23 Aug 2026 10:45:48 -0700 From: Dennis Tighe To: Namjae Jeon , Hyunchul Lee Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH] ntfs: mount read-only when mft records are smaller than the device block Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline An mft record is written with a single bio of exactly mft_record_size bytes. bio_unaligned() rejects a bio whose size is not a multiple of the device's logical block size, so on a volume whose mft records are smaller than that block no mft record can be written at all. On 512n and 512e drives this is a non-issue; however, on 4Kn drives when the mft record (1k) is smaller than the logical block size (4k) mft writes begin to fail. At the same time, other writes that use all 4k will succeed leading to a corruption situation. This is a stopgap change that mounts as read-only. The longer term fix is to perform 4k writes on 4Kn devices when writing the mft; however, that's more involved. Assisted-by: claude:claude-opus-5 Signed-off-by: Dennis Tighe --- >From my testing: Before this patch, on a volume with 20 files already on it: ro mount rc=0 files visible: 20 <- reads are fine rw mount rc=0 files created: 48 <- every creation reported success umount rc=0 5 I/O errors logged next mount: ntfs_mft_record_check(): Record 64 has no FILE magic (0x0) map_mft_record(): Failed with error code 5. ntfs_lookup(): Found stale reference to inode 0x40 ... returning -EIO files: 0 The volume would still mount at the end, but the directory read as empty. Looking at the disk, the mft had not been updated but 4 INDX blocks in the root directory had been written. This occurred since the mft writes from the original mount were failing while other data writes were succeeding. With this patch, same volume and device on my test script: ntfs: (device vda): ntfs_fill_super(): mft record size (1024) is smaller than the device logical block size (4096). Mft records cannot be written. Mounting read-only. mount rc=0 /dev/vda on /mnt/t type ntfs (ro,relatime,...) Reproducing can be done without 4Kn hardware. I used a 4k image and qemu's virtio-blk with logical_block_size=4096. I noted this in the commit message, but this is very much a stopgap measure to prevent corruption before full 4Kn support is added. It seemed safer to me to fallback to read only for now and determine the right path forward later. I believe there are a few options there that are worth some discussion. fs/ntfs/super.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 30481e5d5dd4..ed587bc5e477 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2298,6 +2298,22 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ntfs_debug("Changed device block size to %i bytes (block size bits %i) to match volume sector size.", blocksize, sb->s_blocksize_bits); } + + /* + * If the device's logical block size is larger than the mft record (1k) + * writes to it will currently fail. Reads are unaffected, so we can still + * mount the volume as read-only. + */ + if (vol->mft_record_size < bdev_logical_block_size(sb->s_bdev)) { + if (!sb_rdonly(sb)) { + ntfs_error(sb, + "mft record size (%i) is smaller than the device logical block size (%u). Mft records cannot be written. Mounting read-only.", + vol->mft_record_size, + bdev_logical_block_size(sb->s_bdev)); + sb->s_flags |= SB_RDONLY; + } + } + /* Initialize the cluster and mft allocators. */ ntfs_setup_allocators(vol); /* Setup remaining fields in the super block. */ -- 2.43.0