linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] Refactoring and bugfix
@ 2023-05-08 12:35 Konstantin Komarov
  2023-05-08 12:36 ` [PATCH 01/10] fs/ntfs3: Correct checking while generating attr_list Konstantin Komarov
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:35 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

This series contains various fixes and refactoring for ntfs3.
The loading has been slightly revised.
Added support /proc/fs/ntfs3/<dev>/volinfo and /proc/fs/ntfs3/<dev>/label.

Konstantin Komarov (10):
   fs/ntfs3: Correct checking while generating attr_list
   fs/ntfs3: Fix ntfs_atomic_open
   fs/ntfs3: Mark ntfs dirty when on-disk struct is corrupted
   fs/ntfs3: Alternative boot if primary boot is corrupted
   fs/ntfs3: Do not update primary boot in ntfs_init_from_boot()
   fs/ntfs3: Code formatting
   fs/ntfs3: Code refactoring
   fs/ntfs3: Add ability to format new mft records with bigger/smaller
     header
   fs/ntfs3: Fix endian problem
   fs/ntfs3: Add support /proc/fs/ntfs3/<dev>/volinfo and
     /proc/fs/ntfs3/<dev>/label

  fs/ntfs3/attrib.c   |   2 +-
  fs/ntfs3/attrlist.c |   3 +-
  fs/ntfs3/bitmap.c   |  10 +-
  fs/ntfs3/file.c     |   4 +-
  fs/ntfs3/frecord.c  |  54 +++++----
  fs/ntfs3/fslog.c    |  40 +++----
  fs/ntfs3/fsntfs.c   |  99 ++++++++++++----
  fs/ntfs3/index.c    |  20 ++--
  fs/ntfs3/inode.c    |  23 ++--
  fs/ntfs3/lznt.c     |   6 +-
  fs/ntfs3/namei.c    |  31 ++---
  fs/ntfs3/ntfs.h     | 117 +++++++++++--------
  fs/ntfs3/ntfs_fs.h  |  31 ++---
  fs/ntfs3/record.c   |  10 +-
  fs/ntfs3/run.c      |   4 +-
  fs/ntfs3/super.c    | 279 ++++++++++++++++++++++++++++++++++++++------
  fs/ntfs3/xattr.c    |  16 ++-
  17 files changed, 516 insertions(+), 233 deletions(-)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 01/10] fs/ntfs3: Correct checking while generating attr_list
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
@ 2023-05-08 12:36 ` Konstantin Komarov
  2023-05-08 12:36 ` [PATCH 02/10] fs/ntfs3: Fix ntfs_atomic_open Konstantin Komarov
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:36 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Correct slightly previous commit:
Enhance sanity check while generating attr_list

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/frecord.c | 25 ++++++++++---------------
  1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
index 50214b77c6a3..66f3341c65ec 100644
--- a/fs/ntfs3/frecord.c
+++ b/fs/ntfs3/frecord.c
@@ -813,10 +813,8 @@ int ni_create_attr_list(struct ntfs_inode *ni)
       * Looks like one record_size is always enough.
       */
      le = kmalloc(al_aligned(rs), GFP_NOFS);
-    if (!le) {
-        err = -ENOMEM;
-        goto out;
-    }
+    if (!le)
+        return -ENOMEM;

      mi_get_ref(&ni->mi, &le->ref);
      ni->attr_list.le = le;
@@ -865,14 +863,14 @@ int ni_create_attr_list(struct ntfs_inode *ni)

          if (to_free > free_b) {
              err = -EINVAL;
-            goto out1;
+            goto out;
          }
      }

      /* Allocate child MFT. */
      err = ntfs_look_free_mft(sbi, &rno, is_mft, ni, &mi);
      if (err)
-        goto out1;
+        goto out;

      err = -EINVAL;
      /* Call mi_remove_attr() in reverse order to keep pointers 
'arr_move' valid. */
@@ -884,7 +882,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
          attr = mi_insert_attr(mi, b->type, Add2Ptr(b, name_off),
                        b->name_len, asize, name_off);
          if (!attr)
-            goto out1;
+            goto out;

          mi_get_ref(mi, &le_b[nb]->ref);
          le_b[nb]->id = attr->id;
@@ -895,19 +893,19 @@ int ni_create_attr_list(struct ntfs_inode *ni)

          /* Remove from primary record. */
          if (!mi_remove_attr(NULL, &ni->mi, b))
-            goto out1;
+            goto out;

          if (to_free <= asize)
              break;
          to_free -= asize;
          if (!nb)
-            goto out1;
+            goto out;
      }

      attr = mi_insert_attr(&ni->mi, ATTR_LIST, NULL, 0,
                    lsize + SIZEOF_RESIDENT, SIZEOF_RESIDENT);
      if (!attr)
-        goto out1;
+        goto out;

      attr->non_res = 0;
      attr->flags = 0;
@@ -921,16 +919,13 @@ int ni_create_attr_list(struct ntfs_inode *ni)
      ni->attr_list.dirty = false;

      mark_inode_dirty(&ni->vfs_inode);
-    goto out;
+    return 0;

-out1:
+out:
      kfree(ni->attr_list.le);
      ni->attr_list.le = NULL;
      ni->attr_list.size = 0;
      return err;
-
-out:
-    return 0;
  }

  /*
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/10] fs/ntfs3: Fix ntfs_atomic_open
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
  2023-05-08 12:36 ` [PATCH 01/10] fs/ntfs3: Correct checking while generating attr_list Konstantin Komarov
@ 2023-05-08 12:36 ` Konstantin Komarov
  2023-05-08 12:36 ` [PATCH 03/10] fs/ntfs3: Mark ntfs dirty when on-disk struct is corrupted Konstantin Komarov
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:36 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

This fixes xfstest 633/696.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/namei.c | 15 +++------------
  1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c
index 9736b1e4a0f6..343bce6da58a 100644
--- a/fs/ntfs3/namei.c
+++ b/fs/ntfs3/namei.c
@@ -422,19 +422,10 @@ static int ntfs_atomic_open(struct inode *dir, 
struct dentry *dentry,
       * fnd contains tree's path to insert to.
       * If fnd is not NULL then dir is locked.
       */
-
-    /*
-     * Unfortunately I don't know how to get here correct 'struct 
nameidata *nd'
-     * or 'struct mnt_idmap *idmap'.
-     * See atomic_open in fs/namei.c.
-     * This is why xfstest/633 failed.
-     * Looks like ntfs_atomic_open must accept 'struct mnt_idmap 
*idmap' as argument.
-     */
-
-    inode = ntfs_create_inode(&nop_mnt_idmap, dir, dentry, uni, mode, 0,
-                  NULL, 0, fnd);
+    inode = ntfs_create_inode(mnt_idmap(file->f_path.mnt), dir, dentry, 
uni,
+                  mode, 0, NULL, 0, fnd);
      err = IS_ERR(inode) ? PTR_ERR(inode) :
-                    finish_open(file, dentry, ntfs_file_open);
+                  finish_open(file, dentry, ntfs_file_open);
      dput(d);

  out2:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/10] fs/ntfs3: Mark ntfs dirty when on-disk struct is corrupted
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
  2023-05-08 12:36 ` [PATCH 01/10] fs/ntfs3: Correct checking while generating attr_list Konstantin Komarov
  2023-05-08 12:36 ` [PATCH 02/10] fs/ntfs3: Fix ntfs_atomic_open Konstantin Komarov
@ 2023-05-08 12:36 ` Konstantin Komarov
  2023-05-08 12:37 ` [PATCH 04/10] fs/ntfs3: Alternative boot if primary boot " Konstantin Komarov
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:36 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/fsntfs.c  | 2 +-
  fs/ntfs3/index.c   | 6 ++++++
  fs/ntfs3/ntfs_fs.h | 2 ++
  fs/ntfs3/record.c  | 6 ++++++
  4 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
index 28cc421102e5..21567e58265c 100644
--- a/fs/ntfs3/fsntfs.c
+++ b/fs/ntfs3/fsntfs.c
@@ -178,7 +178,7 @@ int ntfs_fix_post_read(struct NTFS_RECORD_HEADER 
*rhdr, size_t bytes,
      /* Check errors. */
      if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
          fn * SECTOR_SIZE > bytes) {
-        return -EINVAL; /* Native chkntfs returns ok! */
+        return -E_NTFS_CORRUPT;
      }

      /* Get fixup pointer. */
diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c
index 0a48d2d67219..b40da258e684 100644
--- a/fs/ntfs3/index.c
+++ b/fs/ntfs3/index.c
@@ -1113,6 +1113,12 @@ int indx_read(struct ntfs_index *indx, struct 
ntfs_inode *ni, CLST vbn,
      *node = in;

  out:
+    if (err == -E_NTFS_CORRUPT) {
+        ntfs_inode_err(&ni->vfs_inode, "directory corrupted");
+        ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
+        err = -EINVAL;
+    }
+
      if (ib != in->index)
          kfree(ib);

diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index eb01f7e76479..2e4be773728d 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -53,6 +53,8 @@ enum utf16_endian;
  #define E_NTFS_NONRESIDENT        556
  /* NTFS specific error code about punch hole. */
  #define E_NTFS_NOTALIGNED        557
+/* NTFS specific error code when on-disk struct is corrupted. */
+#define E_NTFS_CORRUPT            558


  /* sbi->flags */
diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
index 7060f784c2d7..7974ca35a15c 100644
--- a/fs/ntfs3/record.c
+++ b/fs/ntfs3/record.c
@@ -180,6 +180,12 @@ int mi_read(struct mft_inode *mi, bool is_mft)
      return 0;

  out:
+    if (err == -E_NTFS_CORRUPT) {
+        ntfs_err(sbi->sb, "mft corrupted");
+        ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
+        err = -EINVAL;
+    }
+
      return err;
  }

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/10] fs/ntfs3: Alternative boot if primary boot is corrupted
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (2 preceding siblings ...)
  2023-05-08 12:36 ` [PATCH 03/10] fs/ntfs3: Mark ntfs dirty when on-disk struct is corrupted Konstantin Komarov
@ 2023-05-08 12:37 ` Konstantin Komarov
  2023-05-08 12:38 ` [PATCH 05/10] fs/ntfs3: Do not update primary boot in ntfs_init_from_boot() Konstantin Komarov
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:37 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Some code refactoring added also.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/super.c | 98 +++++++++++++++++++++++++++++++++++-------------
  1 file changed, 71 insertions(+), 27 deletions(-)

diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 5158dd31fd97..ecf899d571d8 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -724,6 +724,8 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,
      struct MFT_REC *rec;
      u16 fn, ao;
      u8 cluster_bits;
+    u32 boot_off = 0;
+    const char *hint = "Primary boot";

      sbi->volume.blocks = dev_size >> PAGE_SHIFT;

@@ -731,11 +733,12 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,
      if (!bh)
          return -EIO;

+check_boot:
      err = -EINVAL;
-    boot = (struct NTFS_BOOT *)bh->b_data;
+    boot = (struct NTFS_BOOT *)Add2Ptr(bh->b_data, boot_off);

      if (memcmp(boot->system_id, "NTFS    ", sizeof("NTFS    ") - 1)) {
-        ntfs_err(sb, "Boot's signature is not NTFS.");
+        ntfs_err(sb, "%s signature is not NTFS.", hint);
          goto out;
      }

@@ -748,14 +751,16 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,
                 boot->bytes_per_sector[0];
      if (boot_sector_size < SECTOR_SIZE ||
          !is_power_of_2(boot_sector_size)) {
-        ntfs_err(sb, "Invalid bytes per sector %u.", boot_sector_size);
+        ntfs_err(sb, "%s: invalid bytes per sector %u.", hint,
+             boot_sector_size);
          goto out;
      }

      /* cluster size: 512, 1K, 2K, 4K, ... 2M */
      sct_per_clst = true_sectors_per_clst(boot);
      if ((int)sct_per_clst < 0 || !is_power_of_2(sct_per_clst)) {
-        ntfs_err(sb, "Invalid sectors per cluster %u.", sct_per_clst);
+        ntfs_err(sb, "%s: invalid sectors per cluster %u.", hint,
+             sct_per_clst);
          goto out;
      }

@@ -771,8 +776,8 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,
      if (mlcn * sct_per_clst >= sectors || mlcn2 * sct_per_clst >= 
sectors) {
          ntfs_err(
              sb,
-            "Start of MFT 0x%llx (0x%llx) is out of volume 0x%llx.",
-            mlcn, mlcn2, sectors);
+            "%s: start of MFT 0x%llx (0x%llx) is out of volume 0x%llx.",
+            hint, mlcn, mlcn2, sectors);
          goto out;
      }

@@ -784,7 +789,7 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      /* Check MFT record size. */
      if (record_size < SECTOR_SIZE || !is_power_of_2(record_size)) {
-        ntfs_err(sb, "Invalid bytes per MFT record %u (%d).",
+        ntfs_err(sb, "%s: invalid bytes per MFT record %u (%d).", hint,
               record_size, boot->record_size);
          goto out;
      }
@@ -801,13 +806,13 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      /* Check index record size. */
      if (sbi->index_size < SECTOR_SIZE || 
!is_power_of_2(sbi->index_size)) {
-        ntfs_err(sb, "Invalid bytes per index %u(%d).", sbi->index_size,
-             boot->index_size);
+        ntfs_err(sb, "%s: invalid bytes per index %u(%d).", hint,
+             sbi->index_size, boot->index_size);
          goto out;
      }

      if (sbi->index_size > MAXIMUM_BYTES_PER_INDEX) {
-        ntfs_err(sb, "Unsupported bytes per index %u.",
+        ntfs_err(sb, "%s: unsupported bytes per index %u.", hint,
               sbi->index_size);
          goto out;
      }
@@ -834,7 +839,7 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      /* Compare boot's cluster and sector. */
      if (sbi->cluster_size < boot_sector_size) {
-        ntfs_err(sb, "Invalid bytes per cluster (%u).",
+        ntfs_err(sb, "%s: invalid bytes per cluster (%u).", hint,
               sbi->cluster_size);
          goto out;
      }
@@ -930,7 +935,46 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      err = 0;

+    if (bh->b_blocknr && !sb_rdonly(sb)) {
+        /*
+          * Alternative boot is ok but primary is not ok.
+          * Update primary boot.
+         */
+        struct buffer_head *bh0 = sb_getblk(sb, 0);
+        if (bh0) {
+            if (buffer_locked(bh0))
+                __wait_on_buffer(bh0);
+
+            lock_buffer(bh0);
+            memcpy(bh0->b_data, boot, sizeof(*boot));
+            set_buffer_uptodate(bh0);
+            mark_buffer_dirty(bh0);
+            unlock_buffer(bh0);
+            if (!sync_dirty_buffer(bh0))
+                ntfs_warn(sb, "primary boot is updated");
+            put_bh(bh0);
+        }
+    }
+
  out:
+    if (err == -EINVAL && !bh->b_blocknr && dev_size > PAGE_SHIFT) {
+        u32 block_size = min_t(u32, sector_size, PAGE_SIZE);
+        u64 lbo = dev_size - sizeof(*boot);
+
+        /*
+          * Try alternative boot (last sector)
+         */
+        brelse(bh);
+
+        sb_set_blocksize(sb, block_size);
+        bh = ntfs_bread(sb, lbo >> blksize_bits(block_size));
+        if (!bh)
+            return -EINVAL;
+
+        boot_off = lbo & (block_size - 1);
+        hint = "Alternative boot";
+        goto check_boot;
+    }
      brelse(bh);

      return err;
@@ -955,6 +999,7 @@ static int ntfs_fill_super(struct super_block *sb, 
struct fs_context *fc)
      struct ATTR_DEF_ENTRY *t;
      u16 *shared;
      struct MFT_REF ref;
+    bool ro = sb_rdonly(sb);

      ref.high = 0;

@@ -1035,6 +1080,10 @@ static int ntfs_fill_super(struct super_block 
*sb, struct fs_context *fc)
      sbi->volume.minor_ver = info->minor_ver;
      sbi->volume.flags = info->flags;
      sbi->volume.ni = ni;
+    if (info->flags & VOLUME_FLAG_DIRTY) {
+        sbi->volume.real_dirty = true;
+        ntfs_info(sb, "It is recommened to use chkdsk.");
+    }

      /* Load $MFTMirr to estimate recs_mirr. */
      ref.low = cpu_to_le32(MFT_REC_MIRR);
@@ -1069,21 +1118,16 @@ static int ntfs_fill_super(struct super_block 
*sb, struct fs_context *fc)

      iput(inode);

-    if (sbi->flags & NTFS_FLAGS_NEED_REPLAY) {
-        if (!sb_rdonly(sb)) {
-            ntfs_warn(sb,
-                  "failed to replay log file. Can't mount rw!");
-            err = -EINVAL;
-            goto out;
-        }
-    } else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) {
-        if (!sb_rdonly(sb) && !options->force) {
-            ntfs_warn(
-                sb,
-                "volume is dirty and \"force\" flag is not set!");
-            err = -EINVAL;
-            goto out;
-        }
+    if ((sbi->flags & NTFS_FLAGS_NEED_REPLAY) && !ro) {
+        ntfs_warn(sb, "failed to replay log file. Can't mount rw!");
+        err = -EINVAL;
+        goto out;
+    }
+
+    if ((sbi->volume.flags & VOLUME_FLAG_DIRTY) && !ro && 
!options->force) {
+        ntfs_warn(sb, "volume is dirty and \"force\" flag is not set!");
+        err = -EINVAL;
+        goto out;
      }

      /* Load $MFT. */
@@ -1173,7 +1217,7 @@ static int ntfs_fill_super(struct super_block *sb, 
struct fs_context *fc)

          bad_len += len;
          bad_frags += 1;
-        if (sb_rdonly(sb))
+        if (ro)
              continue;

          if (wnd_set_used_safe(&sbi->used.bitmap, lcn, len, &tt) || tt) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/10] fs/ntfs3: Do not update primary boot in ntfs_init_from_boot()
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (3 preceding siblings ...)
  2023-05-08 12:37 ` [PATCH 04/10] fs/ntfs3: Alternative boot if primary boot " Konstantin Komarov
@ 2023-05-08 12:38 ` Konstantin Komarov
  2023-05-08 12:38 ` [PATCH 06/10] fs/ntfs3: Code formatting Konstantin Komarov
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:38 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

'cause it may be faked boot.
Let ntfs to be mounted and update boot later.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/super.c | 58 ++++++++++++++++++++++++++++++++----------------
  1 file changed, 39 insertions(+), 19 deletions(-)

diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index ecf899d571d8..2b48b45238ea 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -711,9 +711,16 @@ static u32 true_sectors_per_clst(const struct 
NTFS_BOOT *boot)

  /*
   * ntfs_init_from_boot - Init internal info from on-disk boot sector.
+ *
+ * NTFS mount begins from boot - special formatted 512 bytes.
+ * There are two boots: the first and the last 512 bytes of volume.
+ * The content of boot is not changed during ntfs life.
+ *
+ * NOTE: ntfs.sys checks only first (primary) boot.
+ * chkdsk checks both boots.
   */
  static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
-                   u64 dev_size)
+                   u64 dev_size, struct NTFS_BOOT **boot2)
  {
      struct ntfs_sb_info *sbi = sb->s_fs_info;
      int err;
@@ -937,23 +944,11 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      if (bh->b_blocknr && !sb_rdonly(sb)) {
          /*
-          * Alternative boot is ok but primary is not ok.
-          * Update primary boot.
-         */
-        struct buffer_head *bh0 = sb_getblk(sb, 0);
-        if (bh0) {
-            if (buffer_locked(bh0))
-                __wait_on_buffer(bh0);
-
-            lock_buffer(bh0);
-            memcpy(bh0->b_data, boot, sizeof(*boot));
-            set_buffer_uptodate(bh0);
-            mark_buffer_dirty(bh0);
-            unlock_buffer(bh0);
-            if (!sync_dirty_buffer(bh0))
-                ntfs_warn(sb, "primary boot is updated");
-            put_bh(bh0);
-        }
+         * Alternative boot is ok but primary is not ok.
+         * Do not update primary boot here 'cause it may be faked boot.
+         * Let ntfs to be mounted and update boot later.
+         */
+        *boot2 = kmemdup(boot, sizeof(*boot), GFP_NOFS | __GFP_NOWARN);
      }

  out:
@@ -1000,6 +995,7 @@ static int ntfs_fill_super(struct super_block *sb, 
struct fs_context *fc)
      u16 *shared;
      struct MFT_REF ref;
      bool ro = sb_rdonly(sb);
+    struct NTFS_BOOT *boot2 = NULL;

      ref.high = 0;

@@ -1030,7 +1026,7 @@ static int ntfs_fill_super(struct super_block *sb, 
struct fs_context *fc)

      /* Parse boot. */
      err = ntfs_init_from_boot(sb, bdev_logical_block_size(bdev),
-                  bdev_nr_bytes(bdev));
+                  bdev_nr_bytes(bdev), &boot2);
      if (err)
          goto out;

@@ -1412,6 +1408,29 @@ static int ntfs_fill_super(struct super_block 
*sb, struct fs_context *fc)
          goto put_inode_out;
      }

+    if (boot2) {
+        /*
+         * Alternative boot is ok but primary is not ok.
+         * Volume is recognized as NTFS. Update primary boot.
+         */
+        struct buffer_head *bh0 = sb_getblk(sb, 0);
+        if (bh0) {
+            if (buffer_locked(bh0))
+                __wait_on_buffer(bh0);
+
+            lock_buffer(bh0);
+            memcpy(bh0->b_data, boot2, sizeof(*boot2));
+            set_buffer_uptodate(bh0);
+            mark_buffer_dirty(bh0);
+            unlock_buffer(bh0);
+            if (!sync_dirty_buffer(bh0))
+                ntfs_warn(sb, "primary boot is updated");
+            put_bh(bh0);
+        }
+
+        kfree(boot2);
+    }
+
      return 0;

  put_inode_out:
@@ -1424,6 +1443,7 @@ static int ntfs_fill_super(struct super_block *sb, 
struct fs_context *fc)
      put_mount_options(sbi->options);
      put_ntfs(sbi);
      sb->s_fs_info = NULL;
+    kfree(boot2);

      return err;
  }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/10] fs/ntfs3: Code formatting
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (4 preceding siblings ...)
  2023-05-08 12:38 ` [PATCH 05/10] fs/ntfs3: Do not update primary boot in ntfs_init_from_boot() Konstantin Komarov
@ 2023-05-08 12:38 ` Konstantin Komarov
  2023-05-08 12:38 ` [PATCH 07/10] fs/ntfs3: Code refactoring Konstantin Komarov
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:38 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

clang-format-15 was used to format code according kernel's .clang-format.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/attrib.c  |  2 +-
  fs/ntfs3/bitmap.c  | 10 +++++-----
  fs/ntfs3/file.c    |  4 ++--
  fs/ntfs3/frecord.c | 16 ++++++++++------
  fs/ntfs3/fslog.c   | 40 ++++++++++++++++++++--------------------
  fs/ntfs3/fsntfs.c  |  2 +-
  fs/ntfs3/index.c   | 14 +++++++-------
  fs/ntfs3/inode.c   | 18 +++++++++---------
  fs/ntfs3/lznt.c    |  6 +++---
  fs/ntfs3/namei.c   | 16 ++++++++--------
  fs/ntfs3/ntfs_fs.h | 10 +++++-----
  fs/ntfs3/run.c     |  4 ++--
  fs/ntfs3/super.c   | 17 ++++++++++++-----
  fs/ntfs3/xattr.c   | 16 +++++++---------
  14 files changed, 92 insertions(+), 83 deletions(-)

diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
index 0b8bc66377db..a9d82bbb4729 100644
--- a/fs/ntfs3/attrib.c
+++ b/fs/ntfs3/attrib.c
@@ -573,7 +573,7 @@ int attr_set_size(struct ntfs_inode *ni, enum 
ATTR_TYPE type,
                  sbi, run, vcn, lcn, to_allocate, &pre_alloc,
                  is_mft ? ALLOCATE_MFT : ALLOCATE_DEF, &alen,
                  is_mft ? 0 :
-                           (sbi->record_size -
+                     (sbi->record_size -
                        le32_to_cpu(rec->used) + 8) /
                               3 +
                           1,
diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c
index 9a6c6a09d70c..107e808e06ea 100644
--- a/fs/ntfs3/bitmap.c
+++ b/fs/ntfs3/bitmap.c
@@ -287,8 +287,8 @@ static void wnd_add_free_ext(struct wnd_bitmap *wnd, 
size_t bit, size_t len,
              /* Check bits before 'bit'. */
              ib = wnd->zone_bit == wnd->zone_end ||
                           bit < wnd->zone_end ?
-                       0 :
-                       wnd->zone_end;
+                     0 :
+                     wnd->zone_end;

              while (bit > ib && wnd_is_free_hlp(wnd, bit - 1, 1)) {
                  bit -= 1;
@@ -298,8 +298,8 @@ static void wnd_add_free_ext(struct wnd_bitmap *wnd, 
size_t bit, size_t len,
              /* Check bits after 'end_in'. */
              ib = wnd->zone_bit == wnd->zone_end ||
                           end_in > wnd->zone_bit ?
-                       wnd->nbits :
-                       wnd->zone_bit;
+                     wnd->nbits :
+                     wnd->zone_bit;

              while (end_in < ib && wnd_is_free_hlp(wnd, end_in, 1)) {
                  end_in += 1;
@@ -418,7 +418,7 @@ static void wnd_remove_free_ext(struct wnd_bitmap 
*wnd, size_t bit, size_t len)
          n3 = rb_first(&wnd->count_tree);
          wnd->extent_max =
              n3 ? rb_entry(n3, struct e_node, count.node)->count.key :
-                   0;
+                 0;
          return;
      }

diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index c4983e028d90..4c653945ef08 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -192,7 +192,7 @@ static int ntfs_zero_range(struct inode *inode, u64 
vbo, u64 vbo_to)
      for (; idx < idx_end; idx += 1, from = 0) {
          page_off = (loff_t)idx << PAGE_SHIFT;
          to = (page_off + PAGE_SIZE) > vbo_to ? (vbo_to - page_off) :
-                                 PAGE_SIZE;
+                               PAGE_SIZE;
          iblock = page_off >> inode->i_blkbits;

          page = find_or_create_page(mapping, idx,
@@ -1052,7 +1052,7 @@ static ssize_t ntfs_file_write_iter(struct kiocb 
*iocb, struct iov_iter *from)
          goto out;

      ret = is_compressed(ni) ? ntfs_compress_write(iocb, from) :
-                    __generic_file_write_iter(iocb, from);
+                  __generic_file_write_iter(iocb, from);

  out:
      inode_unlock(inode);
diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
index 66f3341c65ec..4227e3f590a5 100644
--- a/fs/ntfs3/frecord.c
+++ b/fs/ntfs3/frecord.c
@@ -77,7 +77,7 @@ struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni)

      attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
      return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO)) :
-                NULL;
+              NULL;
  }

  /*
@@ -92,7 +92,7 @@ struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni)
      attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);

      return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO5)) :
-                NULL;
+              NULL;
  }

  /*
@@ -517,6 +517,9 @@ ni_ins_new_attr(struct ntfs_inode *ni, struct 
mft_inode *mi,
   */
  static int ni_repack(struct ntfs_inode *ni)
  {
+#if 1
+    return 0;
+#else
      int err = 0;
      struct ntfs_sb_info *sbi = ni->mi.sbi;
      struct mft_inode *mi, *mi_p = NULL;
@@ -639,6 +642,7 @@ static int ni_repack(struct ntfs_inode *ni)

      run_close(&run);
      return err;
+#endif
  }

  /*
@@ -1758,8 +1762,8 @@ int ni_new_attr_flags(struct ntfs_inode *ni, enum 
FILE_ATTRIBUTE new_fa)

      /* Resize nonresident empty attribute in-place only. */
      new_asize = (new_aflags & (ATTR_FLAG_COMPRESSED | 
ATTR_FLAG_SPARSED)) ?
-                  (SIZEOF_NONRESIDENT_EX + 8) :
-                  (SIZEOF_NONRESIDENT + 8);
+                (SIZEOF_NONRESIDENT_EX + 8) :
+                (SIZEOF_NONRESIDENT + 8);

      if (!mi_resize_attr(mi, attr, new_asize - le32_to_cpu(attr->size)))
          return -EOPNOTSUPP;
@@ -3161,8 +3165,8 @@ static bool ni_update_parent(struct ntfs_inode 
*ni, struct NTFS_DUP_INFO *dup,
              __le64 valid_le;

              dup->alloc_size = is_attr_ext(attr) ?
-                            attr->nres.total_size :
-                            attr->nres.alloc_size;
+                          attr->nres.total_size :
+                          attr->nres.alloc_size;
              dup->data_size = attr->nres.data_size;

              if (new_valid > data_size)
diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c
index 57762c5fe68b..12f28cdf5c83 100644
--- a/fs/ntfs3/fslog.c
+++ b/fs/ntfs3/fslog.c
@@ -828,8 +828,8 @@ static inline struct RESTART_TABLE 
*extend_rsttbl(struct RESTART_TABLE *tbl,
      memcpy(rt + 1, tbl + 1, esize * used);

      rt->free_goal = free_goal == ~0u ?
-                      cpu_to_le32(~0u) :
-                      cpu_to_le32(sizeof(struct RESTART_TABLE) +
+                cpu_to_le32(~0u) :
+                cpu_to_le32(sizeof(struct RESTART_TABLE) +
                          free_goal * esize);

      if (tbl->first_free) {
@@ -1090,8 +1090,8 @@ static inline u64 base_lsn(struct ntfs_log *log,
             << log->file_data_bits) +
            ((((is_log_record_end(hdr) &&
                h_lsn <= le64_to_cpu(hdr->record_hdr.last_end_lsn)) ?
-                   le16_to_cpu(hdr->record_hdr.next_record_off) :
-                   log->page_size) +
+                 le16_to_cpu(hdr->record_hdr.next_record_off) :
+                 log->page_size) +
              lsn) >>
             3);

@@ -1299,8 +1299,8 @@ static void log_init_pg_hdr(struct ntfs_log *log, 
u32 sys_page_size,
          log->clst_per_page = 1;

      log->first_page = major_ver >= 2 ?
-                    0x22 * page_size :
-                    ((sys_page_size << 1) + (page_size << 1));
+                  0x22 * page_size :
+                  ((sys_page_size << 1) + (page_size << 1));
      log->major_ver = major_ver;
      log->minor_ver = minor_ver;
  }
@@ -1513,8 +1513,8 @@ static u32 current_log_avail(struct ntfs_log *log)
       * If there is no oldest lsn then start at the first page of the file.
       */
      oldest_off = (log->l_flags & NTFSLOG_NO_OLDEST_LSN) ?
-                   log->first_page :
-                   (log->oldest_lsn_off & ~log->sys_page_mask);
+                 log->first_page :
+                 (log->oldest_lsn_off & ~log->sys_page_mask);

      /*
       * We will use the next log page offset to compute the next free page.
@@ -1522,9 +1522,9 @@ static u32 current_log_avail(struct ntfs_log *log)
       * If we are at the first page then use the end of the file.
       */
      next_free_off = (log->l_flags & NTFSLOG_REUSE_TAIL) ?
-                      log->next_page + log->page_size :
+                log->next_page + log->page_size :
              log->next_page == log->first_page ? log->l_size :
-                                  log->next_page;
+                                log->next_page;

      /* If the two offsets are the same then there is no available 
space. */
      if (oldest_off == next_free_off)
@@ -1535,8 +1535,8 @@ static u32 current_log_avail(struct ntfs_log *log)
       */
      free_bytes =
          oldest_off < next_free_off ?
-                  log->total_avail_pages - (next_free_off - oldest_off) :
-                  oldest_off - next_free_off;
+            log->total_avail_pages - (next_free_off - oldest_off) :
+            oldest_off - next_free_off;

      free_bytes >>= log->page_bits;
      return free_bytes * log->reserved;
@@ -1671,7 +1671,7 @@ static int last_log_lsn(struct ntfs_log *log)

      best_lsn1 = first_tail ? base_lsn(log, first_tail, first_file_off) 
: 0;
      best_lsn2 = second_tail ? base_lsn(log, second_tail, 
second_file_off) :
-                    0;
+                  0;

      if (first_tail && second_tail) {
          if (best_lsn1 > best_lsn2) {
@@ -1767,7 +1767,7 @@ static int last_log_lsn(struct ntfs_log *log)
      page_cnt = page_pos = 1;

      curpage_off = seq_base == log->seq_num ? min(log->next_page, 
page_off) :
-                               log->next_page;
+                         log->next_page;

      wrapped_file =
          curpage_off == log->first_page &&
@@ -1826,8 +1826,8 @@ static int last_log_lsn(struct ntfs_log *log)
              ((lsn_cur >> log->file_data_bits) +
               ((curpage_off <
                 (lsn_to_vbo(log, lsn_cur) & ~log->page_mask)) ?
-                    1 :
-                    0)) != expected_seq) {
+                  1 :
+                  0)) != expected_seq) {
              goto check_tail;
          }

@@ -2643,8 +2643,8 @@ static inline bool check_index_root(const struct 
ATTRIB *attr,
      const struct INDEX_ROOT *root = resident_data(attr);
      u8 index_bits = le32_to_cpu(root->index_block_size) >=
                      sbi->cluster_size ?
-                      sbi->cluster_bits :
-                      SECTOR_SHIFT;
+                sbi->cluster_bits :
+                SECTOR_SHIFT;
      u8 block_clst = root->index_block_clst;

      if (le32_to_cpu(attr->res.data_size) < sizeof(struct INDEX_ROOT) ||
@@ -3861,9 +3861,9 @@ int log_replay(struct ntfs_inode *ni, bool 
*initialized)

      /* If we have a valid page then grab a pointer to the restart area. */
      ra2 = rst_info.valid_page ?
-                Add2Ptr(rst_info.r_page,
+              Add2Ptr(rst_info.r_page,
                    le16_to_cpu(rst_info.r_page->ra_off)) :
-                NULL;
+              NULL;

      if (rst_info.chkdsk_was_run ||
          (ra2 && ra2->client_idx[1] == LFS_NO_CLIENT_LE)) {
diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
index 21567e58265c..1a0527e81ebb 100644
--- a/fs/ntfs3/fsntfs.c
+++ b/fs/ntfs3/fsntfs.c
@@ -173,7 +173,7 @@ int ntfs_fix_post_read(struct NTFS_RECORD_HEADER 
*rhdr, size_t bytes,

      fo = le16_to_cpu(rhdr->fix_off);
      fn = simple ? ((bytes >> SECTOR_SHIFT) + 1) :
-                le16_to_cpu(rhdr->fix_num);
+              le16_to_cpu(rhdr->fix_num);

      /* Check errors. */
      if ((fo & 1) || fo + fn * sizeof(short) > SECTOR_SIZE || !fn-- ||
diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c
index b40da258e684..124c6e822623 100644
--- a/fs/ntfs3/index.c
+++ b/fs/ntfs3/index.c
@@ -432,8 +432,8 @@ static int scan_nres_bitmap(struct ntfs_inode *ni, 
struct ATTRIB *bitmap,
              nbits = 8 * (data_size - vbo);

          ok = nbits > from ?
-                   (*fn)((ulong *)bh->b_data, from, nbits, ret) :
-                   false;
+                 (*fn)((ulong *)bh->b_data, from, nbits, ret) :
+                 false;
          put_bh(bh);

          if (ok) {
@@ -1682,8 +1682,8 @@ static int indx_insert_into_root(struct ntfs_index 
*indx, struct ntfs_inode *ni,

      /* Create alloc and bitmap attributes (if not). */
      err = run_is_empty(&indx->alloc_run) ?
-                indx_create_allocate(indx, ni, &new_vbn) :
-                indx_add_allocate(indx, ni, &new_vbn);
+              indx_create_allocate(indx, ni, &new_vbn) :
+              indx_add_allocate(indx, ni, &new_vbn);

      /* Layout of record may be changed, so rescan root. */
      root = indx_get_root(indx, ni, &attr, &mi);
@@ -1874,8 +1874,8 @@ indx_insert_into_buffer(struct ntfs_index *indx, 
struct ntfs_inode *ni,
                (*indx->cmp)(new_de + 1, le16_to_cpu(new_de->key_size),
                     up_e + 1, le16_to_cpu(up_e->key_size),
                     ctx) < 0 ?
-                    hdr2 :
-                    hdr1,
+                  hdr2 :
+                  hdr1,
                new_de, NULL, ctx);

      indx_mark_used(indx, ni, new_vbn >> indx->idx2vbn_bits);
@@ -2346,7 +2346,7 @@ int indx_delete_entry(struct ntfs_index *indx, 
struct ntfs_inode *ni,
                                    re, ctx,
                                    fnd->level - 1,
                                    fnd) :
-                        indx_insert_into_root(indx, ni, re, e,
+                      indx_insert_into_root(indx, ni, re, e,
                                  ctx, fnd, 0);
              kfree(re);

diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index 6c560245eef4..f699cc053655 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -263,7 +263,7 @@ static struct inode *ntfs_read_mft(struct inode *inode,
              goto next_attr;

          run = ino == MFT_REC_BITMAP ? &sbi->used.bitmap.run :
-                            &ni->file.run;
+                          &ni->file.run;
          break;

      case ATTR_ROOT:
@@ -291,8 +291,8 @@ static struct inode *ntfs_read_mft(struct inode *inode,
              goto out;

          mode = sb->s_root ?
-                     (S_IFDIR | (0777 & sbi->options->fs_dmask_inv)) :
-                     (S_IFDIR | 0777);
+                   (S_IFDIR | (0777 & sbi->options->fs_dmask_inv)) :
+                   (S_IFDIR | 0777);
          goto next_attr;

      case ATTR_ALLOC:
@@ -450,7 +450,7 @@ static struct inode *ntfs_read_mft(struct inode *inode,
          inode->i_op = &ntfs_file_inode_operations;
          inode->i_fop = &ntfs_file_operations;
          inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
-                                    &ntfs_aops;
+                                  &ntfs_aops;
          if (ino != MFT_REC_MFT)
              init_rwsem(&ni->file.run_lock);
      } else if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) ||
@@ -787,7 +787,7 @@ static ssize_t ntfs_direct_IO(struct kiocb *iocb, 
struct iov_iter *iter)

      ret = blockdev_direct_IO(iocb, inode, iter,
                   wr ? ntfs_get_block_direct_IO_W :
-                        ntfs_get_block_direct_IO_R);
+                      ntfs_get_block_direct_IO_R);

      if (ret > 0)
          end = vbo + ret;
@@ -1191,11 +1191,11 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info 
*sbi, const char *symname,
   * - ntfs_symlink
   * - ntfs_mkdir
   * - ntfs_atomic_open
- *
+ *
   * NOTE: if fnd != NULL (ntfs_atomic_open) then @dir is locked
   */
-struct inode *ntfs_create_inode(struct mnt_idmap *idmap,
-                struct inode *dir, struct dentry *dentry,
+struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
+                struct dentry *dentry,
                  const struct cpu_str *uni, umode_t mode,
                  dev_t dev, const char *symname, u32 size,
                  struct ntfs_fnd *fnd)
@@ -1605,7 +1605,7 @@ struct inode *ntfs_create_inode(struct mnt_idmap 
*idmap,
          inode->i_op = &ntfs_file_inode_operations;
          inode->i_fop = &ntfs_file_operations;
          inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
-                                    &ntfs_aops;
+                                  &ntfs_aops;
          init_rwsem(&ni->file.run_lock);
      } else {
          inode->i_op = &ntfs_special_inode_operations;
diff --git a/fs/ntfs3/lznt.c b/fs/ntfs3/lznt.c
index 61e161c7c567..4aae598d6d88 100644
--- a/fs/ntfs3/lznt.c
+++ b/fs/ntfs3/lznt.c
@@ -297,7 +297,7 @@ static inline ssize_t decompress_chunk(u8 *unc, u8 
*unc_end, const u8 *cmpr,
  struct lznt *get_lznt_ctx(int level)
  {
      struct lznt *r = kzalloc(level ? offsetof(struct lznt, hash) :
-                           sizeof(struct lznt),
+                     sizeof(struct lznt),
                   GFP_NOFS);

      if (r)
@@ -393,8 +393,8 @@ ssize_t decompress_lznt(const void *cmpr, size_t 
cmpr_size, void *unc,
          } else {
              /* This chunk does not contain compressed data. */
              unc_use = unc_chunk + LZNT_CHUNK_SIZE > unc_end ?
-                        unc_end - unc_chunk :
-                        LZNT_CHUNK_SIZE;
+                      unc_end - unc_chunk :
+                      LZNT_CHUNK_SIZE;

              if (cmpr_chunk + sizeof(chunk_hdr) + unc_use >
                  cmpr_end) {
diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c
index 343bce6da58a..70f8c859e0ad 100644
--- a/fs/ntfs3/namei.c
+++ b/fs/ntfs3/namei.c
@@ -109,8 +109,8 @@ static int ntfs_create(struct mnt_idmap *idmap, 
struct inode *dir,
  {
      struct inode *inode;

-    inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFREG | mode,
-                  0, NULL, 0, NULL);
+    inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFREG | mode, 0,
+                  NULL, 0, NULL);

      return IS_ERR(inode) ? PTR_ERR(inode) : 0;
  }
@@ -125,8 +125,8 @@ static int ntfs_mknod(struct mnt_idmap *idmap, 
struct inode *dir,
  {
      struct inode *inode;

-    inode = ntfs_create_inode(idmap, dir, dentry, NULL, mode, rdev,
-                  NULL, 0, NULL);
+    inode = ntfs_create_inode(idmap, dir, dentry, NULL, mode, rdev, 
NULL, 0,
+                  NULL);

      return IS_ERR(inode) ? PTR_ERR(inode) : 0;
  }
@@ -199,8 +199,8 @@ static int ntfs_symlink(struct mnt_idmap *idmap, 
struct inode *dir,
      u32 size = strlen(symname);
      struct inode *inode;

-    inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777,
-                  0, symname, size, NULL);
+    inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0,
+                  symname, size, NULL);

      return IS_ERR(inode) ? PTR_ERR(inode) : 0;
  }
@@ -213,8 +213,8 @@ static int ntfs_mkdir(struct mnt_idmap *idmap, 
struct inode *dir,
  {
      struct inode *inode;

-    inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode,
-                  0, NULL, 0, NULL);
+    inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
+                  NULL, 0, NULL);

      return IS_ERR(inode) ? PTR_ERR(inode) : 0;
  }
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 2e4be773728d..6667a75411fc 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -708,8 +708,8 @@ int ntfs_sync_inode(struct inode *inode);
  int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
                struct inode *i2);
  int inode_write_data(struct inode *inode, const void *data, size_t bytes);
-struct inode *ntfs_create_inode(struct mnt_idmap *idmap,
-                struct inode *dir, struct dentry *dentry,
+struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
+                struct dentry *dentry,
                  const struct cpu_str *uni, umode_t mode,
                  dev_t dev, const char *symname, u32 size,
                  struct ntfs_fnd *fnd);
@@ -858,12 +858,12 @@ unsigned long ntfs_names_hash(const u16 *name, 
size_t len, const u16 *upcase,

  /* globals from xattr.c */
  #ifdef CONFIG_NTFS3_FS_POSIX_ACL
-struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap,
-                   struct dentry *dentry, int type);
+struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry 
*dentry,
+                   int type);
  int ntfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
           struct posix_acl *acl, int type);
  int ntfs_init_acl(struct mnt_idmap *idmap, struct inode *inode,
-         struct inode *dir);
+          struct inode *dir);
  #else
  #define ntfs_get_acl NULL
  #define ntfs_set_acl NULL
diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c
index 47612d16c027..cb8cf0161177 100644
--- a/fs/ntfs3/run.c
+++ b/fs/ntfs3/run.c
@@ -434,8 +434,8 @@ bool run_add_entry(struct runs_tree *run, CLST vcn, 
CLST lcn, CLST len,

              if (should_add_tail) {
                  tail_lcn = r->lcn == SPARSE_LCN ?
-                             SPARSE_LCN :
-                             (r->lcn + Tovcn);
+                           SPARSE_LCN :
+                           (r->lcn + Tovcn);
                  tail_vcn = r->vcn + Tovcn;
                  tail_len = r->len - Tovcn;
              }
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 2b48b45238ea..12019bfe1325 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -116,8 +116,8 @@ void ntfs_inode_printk(struct inode *inode, const 
char *fmt, ...)

      /* Use static allocated buffer, if possible. */
      name = atomic_dec_and_test(&s_name_buf_cnt) ?
-                 s_name_buf :
-                 kmalloc(sizeof(s_name_buf), GFP_NOFS);
+               s_name_buf :
+               kmalloc(sizeof(s_name_buf), GFP_NOFS);

      if (name) {
          struct dentry *de = d_find_alias(inode);
@@ -257,6 +257,7 @@ enum Opt {
      Opt_err,
  };

+// clang-format off
  static const struct fs_parameter_spec ntfs_fs_parameters[] = {
      fsparam_u32("uid",            Opt_uid),
      fsparam_u32("gid",            Opt_gid),
@@ -277,9 +278,13 @@ static const struct fs_parameter_spec 
ntfs_fs_parameters[] = {
      fsparam_flag_no("nocase",        Opt_nocase),
      {}
  };
+// clang-format on

  /*
   * Load nls table or if @nls is utf8 then return NULL.
+ *
+ * It is good idea to use here "const char *nls".
+ * But load_nls accepts "char*".
   */
  static struct nls_table *ntfs_load_nls(char *nls)
  {
@@ -790,7 +795,7 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      sbi->record_size = record_size =
          boot->record_size < 0 ? 1 << (-boot->record_size) :
-                          (u32)boot->record_size << cluster_bits;
+                    (u32)boot->record_size << cluster_bits;
      sbi->record_bits = blksize_bits(record_size);
      sbi->attr_size_tr = (5 * record_size >> 4); // ~320 bytes

@@ -808,8 +813,8 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,
      }

      sbi->index_size = boot->index_size < 0 ?
-                    1u << (-boot->index_size) :
-                    (u32)boot->index_size << cluster_bits;
+                  1u << (-boot->index_size) :
+                  (u32)boot->index_size << cluster_bits;

      /* Check index record size. */
      if (sbi->index_size < SECTOR_SIZE || 
!is_power_of_2(sbi->index_size)) {
@@ -1537,12 +1542,14 @@ static void ntfs_fs_free(struct fs_context *fc)
          put_mount_options(opts);
  }

+// clang-format off
  static const struct fs_context_operations ntfs_context_ops = {
      .parse_param    = ntfs_fs_parse_param,
      .get_tree    = ntfs_fs_get_tree,
      .reconfigure    = ntfs_fs_reconfigure,
      .free        = ntfs_fs_free,
  };
+// clang-format on

  /*
   * ntfs_init_fs_context - Initialize sbi and opts
diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c
index 26787c2bbf75..023f314e8950 100644
--- a/fs/ntfs3/xattr.c
+++ b/fs/ntfs3/xattr.c
@@ -24,7 +24,7 @@
  static inline size_t unpacked_ea_size(const struct EA_FULL *ea)
  {
      return ea->size ? le32_to_cpu(ea->size) :
-                ALIGN(struct_size(ea, name,
+              ALIGN(struct_size(ea, name,
                          1 + ea->name_len +
                              le16_to_cpu(ea->elength)),
                  4);
@@ -528,8 +528,8 @@ static noinline int ntfs_set_ea(struct inode *inode, 
const char *name,
  /*
   * ntfs_get_acl - inode_operations::get_acl
   */
-struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap,
-                   struct dentry *dentry, int type)
+struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry 
*dentry,
+                   int type)
  {
      struct inode *inode = d_inode(dentry);
      struct ntfs_inode *ni = ntfs_i(inode);
@@ -596,8 +596,7 @@ static noinline int ntfs_set_acl_ex(struct mnt_idmap 
*idmap,
      case ACL_TYPE_ACCESS:
          /* Do not change i_mode if we are in init_acl */
          if (acl && !init_acl) {
-            err = posix_acl_update_mode(idmap, inode, &mode,
-                            &acl);
+            err = posix_acl_update_mode(idmap, inode, &mode, &acl);
              if (err)
                  return err;
          }
@@ -820,10 +819,9 @@ static int ntfs_getxattr(const struct xattr_handler 
*handler, struct dentry *de,
   * ntfs_setxattr - inode_operations::setxattr
   */
  static noinline int ntfs_setxattr(const struct xattr_handler *handler,
-                  struct mnt_idmap *idmap,
-                  struct dentry *de, struct inode *inode,
-                  const char *name, const void *value,
-                  size_t size, int flags)
+                  struct mnt_idmap *idmap, struct dentry *de,
+                  struct inode *inode, const char *name,
+                  const void *value, size_t size, int flags)
  {
      int err = -EINVAL;
      struct ntfs_inode *ni = ntfs_i(inode);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/10] fs/ntfs3: Code refactoring
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (5 preceding siblings ...)
  2023-05-08 12:38 ` [PATCH 06/10] fs/ntfs3: Code formatting Konstantin Komarov
@ 2023-05-08 12:38 ` Konstantin Komarov
  2023-05-08 12:39 ` [PATCH 08/10] fs/ntfs3: Add ability to format new mft records with bigger/smaller header Konstantin Komarov
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:38 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Check functions arguments. Use u8 instead of size_t for ntfs names, more 
consts and other.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/attrlist.c |   3 +-
  fs/ntfs3/frecord.c  |   2 +-
  fs/ntfs3/fsntfs.c   |  37 +++++++--------
  fs/ntfs3/inode.c    |   5 +-
  fs/ntfs3/ntfs.h     | 108 ++++++++++++++++++++++++--------------------
  fs/ntfs3/ntfs_fs.h  |  12 ++---
  fs/ntfs3/record.c   |   2 +-
  7 files changed, 88 insertions(+), 81 deletions(-)

diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c
index 81c22df27c72..42631b31adf1 100644
--- a/fs/ntfs3/attrlist.c
+++ b/fs/ntfs3/attrlist.c
@@ -375,8 +375,7 @@ bool al_remove_le(struct ntfs_inode *ni, struct 
ATTR_LIST_ENTRY *le)
   * al_delete_le - Delete first le from the list which matches its 
parameters.
   */
  bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
-          const __le16 *name, size_t name_len,
-          const struct MFT_REF *ref)
+          const __le16 *name, u8 name_len, const struct MFT_REF *ref)
  {
      u16 size;
      struct ATTR_LIST_ENTRY *le;
diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
index 4227e3f590a5..be59bd399fd1 100644
--- a/fs/ntfs3/frecord.c
+++ b/fs/ntfs3/frecord.c
@@ -384,7 +384,7 @@ bool ni_add_subrecord(struct ntfs_inode *ni, CLST 
rno, struct mft_inode **mi)
   * ni_remove_attr - Remove all attributes for the given type/name/id.
   */
  int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
-           const __le16 *name, size_t name_len, bool base_only,
+           const __le16 *name, u8 name_len, bool base_only,
             const __le16 *id)
  {
      int err;
diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
index 1a0527e81ebb..1c05c088d1c6 100644
--- a/fs/ntfs3/fsntfs.c
+++ b/fs/ntfs3/fsntfs.c
@@ -1661,7 +1661,8 @@ int ntfs_vbo_to_lbo(struct ntfs_sb_info *sbi, 
const struct runs_tree *run,
      return 0;
  }

-struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST rno, 
bool dir)
+struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST rno,
+                  enum RECORD_FLAG flag)
  {
      int err = 0;
      struct super_block *sb = sbi->sb;
@@ -1673,8 +1674,7 @@ struct ntfs_inode *ntfs_new_inode(struct 
ntfs_sb_info *sbi, CLST rno, bool dir)

      ni = ntfs_i(inode);

-    err = mi_format_new(&ni->mi, sbi, rno, dir ? RECORD_FLAG_DIR : 0,
-                false);
+    err = mi_format_new(&ni->mi, sbi, rno, flag, false);
      if (err)
          goto out;

@@ -1937,7 +1937,7 @@ int ntfs_security_init(struct ntfs_sb_info *sbi)
              break;

          sii_e = (struct NTFS_DE_SII *)ne;
-        if (le16_to_cpu(ne->view.data_size) < SIZEOF_SECURITY_HDR)
+        if (le16_to_cpu(ne->view.data_size) < sizeof(sii_e->sec_hdr))
              continue;

          next_id = le32_to_cpu(sii_e->sec_id) + 1;
@@ -1998,18 +1998,18 @@ int ntfs_get_security_by_id(struct ntfs_sb_info 
*sbi, __le32 security_id,
          goto out;

      t32 = le32_to_cpu(sii_e->sec_hdr.size);
-    if (t32 < SIZEOF_SECURITY_HDR) {
+    if (t32 < sizeof(struct SECURITY_HDR)) {
          err = -EINVAL;
          goto out;
      }

-    if (t32 > SIZEOF_SECURITY_HDR + 0x10000) {
+    if (t32 > sizeof(struct SECURITY_HDR) + 0x10000) {
          /* Looks like too big security. 0x10000 - is arbitrary big 
number. */
          err = -EFBIG;
          goto out;
      }

-    *size = t32 - SIZEOF_SECURITY_HDR;
+    *size = t32 - sizeof(struct SECURITY_HDR);

      p = kmalloc(*size, GFP_NOFS);
      if (!p) {
@@ -2023,14 +2023,14 @@ int ntfs_get_security_by_id(struct ntfs_sb_info 
*sbi, __le32 security_id,
      if (err)
          goto out;

-    if (memcmp(&d_security, &sii_e->sec_hdr, SIZEOF_SECURITY_HDR)) {
+    if (memcmp(&d_security, &sii_e->sec_hdr, sizeof(d_security))) {
          err = -EINVAL;
          goto out;
      }

      err = ntfs_read_run_nb(sbi, &ni->file.run,
                     le64_to_cpu(sii_e->sec_hdr.off) +
-                       SIZEOF_SECURITY_HDR,
+                       sizeof(struct SECURITY_HDR),
                     p, *size, NULL);
      if (err)
          goto out;
@@ -2069,7 +2069,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
      struct NTFS_DE_SDH sdh_e;
      struct NTFS_DE_SII sii_e;
      struct SECURITY_HDR *d_security;
-    u32 new_sec_size = size_sd + SIZEOF_SECURITY_HDR;
+    u32 new_sec_size = size_sd + sizeof(struct SECURITY_HDR);
      u32 aligned_sec_size = ALIGN(new_sec_size, 16);
      struct SECURITY_KEY hash_key;
      struct ntfs_fnd *fnd_sdh = NULL;
@@ -2207,14 +2207,14 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
      /* Fill SII entry. */
      sii_e.de.view.data_off =
          cpu_to_le16(offsetof(struct NTFS_DE_SII, sec_hdr));
-    sii_e.de.view.data_size = cpu_to_le16(SIZEOF_SECURITY_HDR);
+    sii_e.de.view.data_size = cpu_to_le16(sizeof(struct SECURITY_HDR));
      sii_e.de.view.res = 0;
-    sii_e.de.size = cpu_to_le16(SIZEOF_SII_DIRENTRY);
+    sii_e.de.size = cpu_to_le16(sizeof(struct NTFS_DE_SII));
      sii_e.de.key_size = cpu_to_le16(sizeof(d_security->key.sec_id));
      sii_e.de.flags = 0;
      sii_e.de.res = 0;
      sii_e.sec_id = d_security->key.sec_id;
-    memcpy(&sii_e.sec_hdr, d_security, SIZEOF_SECURITY_HDR);
+    memcpy(&sii_e.sec_hdr, d_security, sizeof(struct SECURITY_HDR));

      err = indx_insert_entry(indx_sii, ni, &sii_e.de, NULL, NULL, 0);
      if (err)
@@ -2223,7 +2223,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
      /* Fill SDH entry. */
      sdh_e.de.view.data_off =
          cpu_to_le16(offsetof(struct NTFS_DE_SDH, sec_hdr));
-    sdh_e.de.view.data_size = cpu_to_le16(SIZEOF_SECURITY_HDR);
+    sdh_e.de.view.data_size = cpu_to_le16(sizeof(struct SECURITY_HDR));
      sdh_e.de.view.res = 0;
      sdh_e.de.size = cpu_to_le16(SIZEOF_SDH_DIRENTRY);
      sdh_e.de.key_size = cpu_to_le16(sizeof(sdh_e.key));
@@ -2231,7 +2231,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
      sdh_e.de.res = 0;
      sdh_e.key.hash = d_security->key.hash;
      sdh_e.key.sec_id = d_security->key.sec_id;
-    memcpy(&sdh_e.sec_hdr, d_security, SIZEOF_SECURITY_HDR);
+    memcpy(&sdh_e.sec_hdr, d_security, sizeof(struct SECURITY_HDR));
      sdh_e.magic[0] = cpu_to_le16('I');
      sdh_e.magic[1] = cpu_to_le16('I');

@@ -2522,7 +2522,8 @@ void mark_as_free_ex(struct ntfs_sb_info *sbi, 
CLST lcn, CLST len, bool trim)
  /*
   * run_deallocate - Deallocate clusters.
   */
-int run_deallocate(struct ntfs_sb_info *sbi, struct runs_tree *run, 
bool trim)
+int run_deallocate(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+           bool trim)
  {
      CLST lcn, len;
      size_t idx = 0;
@@ -2578,13 +2579,13 @@ static inline bool 
name_has_forbidden_chars(const struct le_str *fname)
      return false;
  }

-static inline bool is_reserved_name(struct ntfs_sb_info *sbi,
+static inline bool is_reserved_name(const struct ntfs_sb_info *sbi,
                      const struct le_str *fname)
  {
      int port_digit;
      const __le16 *name = fname->name;
      int len = fname->len;
-    u16 *upcase = sbi->upcase;
+    const u16 *upcase = sbi->upcase;

      /* check for 3 chars reserved names (device names) */
      /* name by itself or with any extension is forbidden */
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index f699cc053655..dc7e7ab701c6 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -1309,7 +1309,7 @@ struct inode *ntfs_create_inode(struct mnt_idmap 
*idmap, struct inode *dir,
      if (err)
          goto out2;

-    ni = ntfs_new_inode(sbi, ino, fa & FILE_ATTRIBUTE_DIRECTORY);
+    ni = ntfs_new_inode(sbi, ino, S_ISDIR(mode) ? RECORD_FLAG_DIR : 0);
      if (IS_ERR(ni)) {
          err = PTR_ERR(ni);
          ni = NULL;
@@ -1437,8 +1437,7 @@ struct inode *ntfs_create_inode(struct mnt_idmap 
*idmap, struct inode *dir,

          root = Add2Ptr(attr, sizeof(I30_NAME) + SIZEOF_RESIDENT);
          memcpy(root, dir_root, offsetof(struct INDEX_ROOT, ihdr));
-        root->ihdr.de_off =
-            cpu_to_le32(sizeof(struct INDEX_HDR)); // 0x10
+        root->ihdr.de_off = cpu_to_le32(sizeof(struct INDEX_HDR));
          root->ihdr.used = cpu_to_le32(sizeof(struct INDEX_HDR) +
                            sizeof(struct NTFS_DE));
          root->ihdr.total = root->ihdr.used;
diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h
index 90151e56c122..3ec2eaf31996 100644
--- a/fs/ntfs3/ntfs.h
+++ b/fs/ntfs3/ntfs.h
@@ -95,11 +95,10 @@ enum RECORD_NUM {
      MFT_REC_BITMAP        = 6,
      MFT_REC_BOOT        = 7,
      MFT_REC_BADCLUST    = 8,
-    //MFT_REC_QUOTA        = 9,
-    MFT_REC_SECURE        = 9, // NTFS 3.0
+    MFT_REC_SECURE        = 9,
      MFT_REC_UPCASE        = 10,
-    MFT_REC_EXTEND        = 11, // NTFS 3.0
-    MFT_REC_RESERVED    = 11,
+    MFT_REC_EXTEND        = 11,
+    MFT_REC_RESERVED    = 12,
      MFT_REC_FREE        = 16,
      MFT_REC_USER        = 24,
  };
@@ -109,7 +108,6 @@ enum ATTR_TYPE {
      ATTR_STD        = cpu_to_le32(0x10),
      ATTR_LIST        = cpu_to_le32(0x20),
      ATTR_NAME        = cpu_to_le32(0x30),
-    // ATTR_VOLUME_VERSION on Nt4
      ATTR_ID            = cpu_to_le32(0x40),
      ATTR_SECURE        = cpu_to_le32(0x50),
      ATTR_LABEL        = cpu_to_le32(0x60),
@@ -118,7 +116,6 @@ enum ATTR_TYPE {
      ATTR_ROOT        = cpu_to_le32(0x90),
      ATTR_ALLOC        = cpu_to_le32(0xA0),
      ATTR_BITMAP        = cpu_to_le32(0xB0),
-    // ATTR_SYMLINK on Nt4
      ATTR_REPARSE        = cpu_to_le32(0xC0),
      ATTR_EA_INFO        = cpu_to_le32(0xD0),
      ATTR_EA            = cpu_to_le32(0xE0),
@@ -144,6 +141,7 @@ enum FILE_ATTRIBUTE {
      FILE_ATTRIBUTE_ENCRYPTED    = cpu_to_le32(0x00004000),
      FILE_ATTRIBUTE_VALID_FLAGS    = cpu_to_le32(0x00007fb7),
      FILE_ATTRIBUTE_DIRECTORY    = cpu_to_le32(0x10000000),
+    FILE_ATTRIBUTE_INDEX        = cpu_to_le32(0x20000000)
  };

  static_assert(sizeof(enum FILE_ATTRIBUTE) == 4);
@@ -266,7 +264,7 @@ enum RECORD_FLAG {
      RECORD_FLAG_IN_USE    = cpu_to_le16(0x0001),
      RECORD_FLAG_DIR        = cpu_to_le16(0x0002),
      RECORD_FLAG_SYSTEM    = cpu_to_le16(0x0004),
-    RECORD_FLAG_UNKNOWN    = cpu_to_le16(0x0008),
+    RECORD_FLAG_INDEX    = cpu_to_le16(0x0008),
  };

  /* MFT Record structure. */
@@ -331,18 +329,18 @@ struct ATTR_NONRESIDENT {
      __le64 svcn;        // 0x10: Starting VCN of this segment.
      __le64 evcn;        // 0x18: End VCN of this segment.
      __le16 run_off;        // 0x20: Offset to packed runs.
-    //  Unit of Compression size for this stream, expressed
-    //  as a log of the cluster size.
+    // Unit of Compression size for this stream, expressed
+    // as a log of the cluster size.
      //
-    //    0 means file is not compressed
-    //    1, 2, 3, and 4 are potentially legal values if the
-    //        stream is compressed, however the implementation
-    //        may only choose to use 4, or possibly 3.  Note
-    //        that 4 means cluster size time 16.    If convenient
-    //        the implementation may wish to accept a
-    //        reasonable range of legal values here (1-5?),
-    //        even if the implementation only generates
-    //        a smaller set of values itself.
+    // 0 means file is not compressed
+    // 1, 2, 3, and 4 are potentially legal values if the
+    // stream is compressed, however the implementation
+    // may only choose to use 4, or possibly 3.
+        // Note that 4 means cluster size time 16.
+        // If convenient the implementation may wish to accept a
+    // reasonable range of legal values here (1-5?),
+    // even if the implementation only generates
+    // a smaller set of values itself.
      u8 c_unit;        // 0x22:
      u8 res1[5];        // 0x23:
      __le64 alloc_size;    // 0x28: The allocated size of attribute in 
bytes.
@@ -836,16 +834,22 @@ static_assert(sizeof(struct ATTR_DEF_ENTRY) == 0xa0);
  /* Object ID (0x40) */
  struct OBJECT_ID {
      struct GUID ObjId;    // 0x00: Unique Id assigned to file.
-    struct GUID BirthVolumeId; // 0x10: Birth Volume Id is the Object 
Id of the Volume on.
-                // which the Object Id was allocated. It never changes.
-    struct GUID BirthObjectId; // 0x20: Birth Object Id is the first 
Object Id that was
-                // ever assigned to this MFT Record. I.e. If the Object Id
-                // is changed for some reason, this field will reflect the
-                // original value of the Object Id.
-    struct GUID DomainId;    // 0x30: Domain Id is currently unused but 
it is intended to be
-                // used in a network environment where the local machine is
-                // part of a Windows 2000 Domain. This may be used in a 
Windows
-                // 2000 Advanced Server managed domain.
+
+    // Birth Volume Id is the Object Id of the Volume on.
+    // which the Object Id was allocated. It never changes.
+    struct GUID BirthVolumeId; //0x10:
+
+    // Birth Object Id is the first Object Id that was
+    // ever assigned to this MFT Record. I.e. If the Object Id
+    // is changed for some reason, this field will reflect the
+    // original value of the Object Id.
+    struct GUID BirthObjectId; // 0x20:
+
+    // Domain Id is currently unused but it is intended to be
+    // used in a network environment where the local machine is
+    // part of a Windows 2000 Domain. This may be used in a Windows
+    // 2000 Advanced Server managed domain.
+    struct GUID DomainId;    // 0x30:
  };

  static_assert(sizeof(struct OBJECT_ID) == 0x40);
@@ -855,32 +859,35 @@ struct NTFS_DE_O {
      struct NTFS_DE de;
      struct GUID ObjId;    // 0x10: Unique Id assigned to file.
      struct MFT_REF ref;    // 0x20: MFT record number with this file.
-    struct GUID BirthVolumeId; // 0x28: Birth Volume Id is the Object 
Id of the Volume on
-                // which the Object Id was allocated. It never changes.
-    struct GUID BirthObjectId; // 0x38: Birth Object Id is the first 
Object Id that was
-                // ever assigned to this MFT Record. I.e. If the Object Id
-                // is changed for some reason, this field will reflect the
-                // original value of the Object Id.
-                // This field is valid if data_size == 0x48.
-    struct GUID BirthDomainId; // 0x48: Domain Id is currently unused 
but it is intended
-                // to be used in a network environment where the local
-                // machine is part of a Windows 2000 Domain. This may be
-                // used in a Windows 2000 Advanced Server managed domain.
+
+    // Birth Volume Id is the Object Id of the Volume on
+    // which the Object Id was allocated. It never changes.
+    struct GUID BirthVolumeId; // 0x28:
+
+    // Birth Object Id is the first Object Id that was
+    // ever assigned to this MFT Record. I.e. If the Object Id
+    // is changed for some reason, this field will reflect the
+    // original value of the Object Id.
+    // This field is valid if data_size == 0x48.
+    struct GUID BirthObjectId; // 0x38:
+
+    // Domain Id is currently unused but it is intended
+    // to be used in a network environment where the local
+    // machine is part of a Windows 2000 Domain. This may be
+    // used in a Windows 2000 Advanced Server managed domain.
+    struct GUID BirthDomainId; // 0x48:
  };

  static_assert(sizeof(struct NTFS_DE_O) == 0x58);

-#define NTFS_OBJECT_ENTRY_DATA_SIZE1                           \
-    0x38 // struct NTFS_DE_O.BirthDomainId is not used
-#define NTFS_OBJECT_ENTRY_DATA_SIZE2                           \
-    0x48 // struct NTFS_DE_O.BirthDomainId is used
-
  /* Q Directory entry structure ( rule = 0x11 ) */
  struct NTFS_DE_Q {
      struct NTFS_DE de;
      __le32 owner_id;    // 0x10: Unique Id assigned to file
+
+    /* here is 0x30 bytes of user quota. NOTE: 4 byte aligned! */
      __le32 Version;        // 0x14: 0x02
-    __le32 flags2;        // 0x18: Quota flags, see above
+    __le32 Flags;        // 0x18: Quota flags, see above
      __le64 BytesUsed;    // 0x1C:
      __le64 ChangeTime;    // 0x24:
      __le64 WarningLimit;    // 0x28:
@@ -888,9 +895,9 @@ struct NTFS_DE_Q {
      __le64 ExceededTime;    // 0x3C:

      // SID is placed here
-}; // sizeof() = 0x44
+}__packed; // sizeof() = 0x44

-#define SIZEOF_NTFS_DE_Q 0x44
+static_assert(sizeof(struct NTFS_DE_Q) == 0x44);

  #define SecurityDescriptorsBlockSize 0x40000 // 256K
  #define SecurityDescriptorMaxSize    0x20000 // 128K
@@ -912,7 +919,7 @@ struct SECURITY_HDR {
       */
  } __packed;

-#define SIZEOF_SECURITY_HDR 0x14
+static_assert(sizeof(struct SECURITY_HDR) == 0x14);

  /* SII Directory entry structure */
  struct NTFS_DE_SII {
@@ -921,7 +928,8 @@ struct NTFS_DE_SII {
      struct SECURITY_HDR sec_hdr;    // 0x14:
  } __packed;

-#define SIZEOF_SII_DIRENTRY 0x28
+static_assert(offsetof(struct NTFS_DE_SII, sec_hdr) == 0x14);
+static_assert(sizeof(struct NTFS_DE_SII) == 0x28);

  /* SDH Directory entry structure */
  struct NTFS_DE_SDH {
@@ -1155,7 +1163,7 @@ struct REPARSE_DATA_BUFFER {

  #define FILE_NEED_EA 0x80 // See ntifs.h
  /*
- *FILE_NEED_EA, indicates that the file to which the EA belongs cannot be
+ * FILE_NEED_EA, indicates that the file to which the EA belongs cannot be
   * interpreted without understanding the associated extended attributes.
   */
  struct EA_INFO {
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 6667a75411fc..98b61e4b3215 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -467,8 +467,7 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE 
type, const __le16 *name,
            struct ATTR_LIST_ENTRY **new_le);
  bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le);
  bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
-          const __le16 *name, size_t name_len,
-          const struct MFT_REF *ref);
+          const __le16 *name, u8 name_len, const struct MFT_REF *ref);
  int al_update(struct ntfs_inode *ni, int sync);
  static inline size_t al_aligned(size_t size)
  {
@@ -527,7 +526,7 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, 
enum ATTR_TYPE type,
  int ni_load_all_mi(struct ntfs_inode *ni);
  bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct 
mft_inode **mi);
  int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
-           const __le16 *name, size_t name_len, bool base_only,
+           const __le16 *name, u8 name_len, bool base_only,
             const __le16 *id);
  int ni_create_attr_list(struct ntfs_inode *ni);
  int ni_expand_list(struct ntfs_inode *ni);
@@ -631,7 +630,7 @@ int ntfs_bio_fill_1(struct ntfs_sb_info *sbi, const 
struct runs_tree *run);
  int ntfs_vbo_to_lbo(struct ntfs_sb_info *sbi, const struct runs_tree *run,
              u64 vbo, u64 *lbo, u64 *bytes);
  struct ntfs_inode *ntfs_new_inode(struct ntfs_sb_info *sbi, CLST nRec,
-                  bool dir);
+                  enum RECORD_FLAG flag);
  extern const u8 s_default_security[0x50];
  bool is_sd_valid(const struct SECURITY_DESCRIPTOR_RELATIVE *sd, u32 len);
  int ntfs_security_init(struct ntfs_sb_info *sbi);
@@ -649,7 +648,8 @@ int ntfs_insert_reparse(struct ntfs_sb_info *sbi, 
__le32 rtag,
  int ntfs_remove_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
              const struct MFT_REF *ref);
  void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, 
bool trim);
-int run_deallocate(struct ntfs_sb_info *sbi, struct runs_tree *run, 
bool trim);
+int run_deallocate(struct ntfs_sb_info *sbi, const struct runs_tree *run,
+           bool trim);
  bool valid_windows_name(struct ntfs_sb_info *sbi, const struct le_str 
*name);

  /* Globals from index.c */
@@ -738,7 +738,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr);
  // TODO: id?
  struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
                  enum ATTR_TYPE type, const __le16 *name,
-                size_t name_len, const __le16 *id);
+                u8 name_len, const __le16 *id);
  static inline struct ATTRIB *rec_find_attr_le(struct mft_inode *rec,
                            struct ATTR_LIST_ENTRY *le)
  {
diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
index 7974ca35a15c..e73ca2df42eb 100644
--- a/fs/ntfs3/record.c
+++ b/fs/ntfs3/record.c
@@ -302,7 +302,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)
   */
  struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
                  enum ATTR_TYPE type, const __le16 *name,
-                size_t name_len, const __le16 *id)
+                u8 name_len, const __le16 *id)
  {
      u32 type_in = le32_to_cpu(type);
      u32 atype;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/10] fs/ntfs3: Add ability to format new mft records with bigger/smaller header
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (6 preceding siblings ...)
  2023-05-08 12:38 ` [PATCH 07/10] fs/ntfs3: Code refactoring Konstantin Komarov
@ 2023-05-08 12:39 ` Konstantin Komarov
  2023-05-08 12:39 ` [PATCH 09/10] fs/ntfs3: Fix endian problem Konstantin Komarov
  2023-05-08 12:40 ` [PATCH 10/10] fs/ntfs3: Add support /proc/fs/ntfs3/<dev>/volinfo and /proc/fs/ntfs3/<dev>/label Konstantin Komarov
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:39 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Just define in ntfs.h
     #define MFTRECORD_FIXUP_OFFSET  MFTRECORD_FIXUP_OFFSET_1
or
     #define MFTRECORD_FIXUP_OFFSET  MFTRECORD_FIXUP_OFFSET_3

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/ntfs.h   | 9 +++++++++
  fs/ntfs3/record.c | 2 ++
  fs/ntfs3/super.c  | 6 +++---
  3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h
index 3ec2eaf31996..98b76d1b09e7 100644
--- a/fs/ntfs3/ntfs.h
+++ b/fs/ntfs3/ntfs.h
@@ -288,6 +288,15 @@ struct MFT_REC {

  #define MFTRECORD_FIXUP_OFFSET_1 offsetof(struct MFT_REC, res)
  #define MFTRECORD_FIXUP_OFFSET_3 offsetof(struct MFT_REC, fixups)
+/*
+ * define MFTRECORD_FIXUP_OFFSET as MFTRECORD_FIXUP_OFFSET_3 (0x30)
+ * to format new mft records with bigger header (as current ntfs.sys does)
+ *
+ * define MFTRECORD_FIXUP_OFFSET as MFTRECORD_FIXUP_OFFSET_1 (0x2A)
+ * to format new mft records with smaller header (as old ntfs.sys did)
+ * Both variants are valid.
+ */
+#define MFTRECORD_FIXUP_OFFSET  MFTRECORD_FIXUP_OFFSET_1

  static_assert(MFTRECORD_FIXUP_OFFSET_1 == 0x2A);
  static_assert(MFTRECORD_FIXUP_OFFSET_3 == 0x30);
diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
index e73ca2df42eb..c12ebffc94da 100644
--- a/fs/ntfs3/record.c
+++ b/fs/ntfs3/record.c
@@ -388,6 +388,8 @@ int mi_format_new(struct mft_inode *mi, struct 
ntfs_sb_info *sbi, CLST rno,

      rec->seq = cpu_to_le16(seq);
      rec->flags = RECORD_FLAG_IN_USE | flags;
+    if (MFTRECORD_FIXUP_OFFSET == MFTRECORD_FIXUP_OFFSET_3)
+        rec->mft_record = cpu_to_le32(rno);

      mi->dirty = true;

diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 12019bfe1325..7ab0a79c7d84 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -867,7 +867,7 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,
      }

      sbi->max_bytes_per_attr =
-        record_size - ALIGN(MFTRECORD_FIXUP_OFFSET_1, 8) -
+        record_size - ALIGN(MFTRECORD_FIXUP_OFFSET, 8) -
          ALIGN(((record_size >> SECTOR_SHIFT) * sizeof(short)), 8) -
          ALIGN(sizeof(enum ATTR_TYPE), 8);

@@ -909,10 +909,10 @@ static int ntfs_init_from_boot(struct super_block 
*sb, u32 sector_size,

      sbi->new_rec = rec;
      rec->rhdr.sign = NTFS_FILE_SIGNATURE;
-    rec->rhdr.fix_off = cpu_to_le16(MFTRECORD_FIXUP_OFFSET_1);
+    rec->rhdr.fix_off = cpu_to_le16(MFTRECORD_FIXUP_OFFSET);
      fn = (sbi->record_size >> SECTOR_SHIFT) + 1;
      rec->rhdr.fix_num = cpu_to_le16(fn);
-    ao = ALIGN(MFTRECORD_FIXUP_OFFSET_1 + sizeof(short) * fn, 8);
+    ao = ALIGN(MFTRECORD_FIXUP_OFFSET + sizeof(short) * fn, 8);
      rec->attr_off = cpu_to_le16(ao);
      rec->used = cpu_to_le32(ao + ALIGN(sizeof(enum ATTR_TYPE), 8));
      rec->total = cpu_to_le32(sbi->record_size);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/10] fs/ntfs3: Fix endian problem
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (7 preceding siblings ...)
  2023-05-08 12:39 ` [PATCH 08/10] fs/ntfs3: Add ability to format new mft records with bigger/smaller header Konstantin Komarov
@ 2023-05-08 12:39 ` Konstantin Komarov
  2023-05-08 12:40 ` [PATCH 10/10] fs/ntfs3: Add support /proc/fs/ntfs3/<dev>/volinfo and /proc/fs/ntfs3/<dev>/label Konstantin Komarov
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:39 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/frecord.c | 11 +++++------
  fs/ntfs3/ntfs_fs.h |  2 +-
  2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
index be59bd399fd1..16bd9faa2d28 100644
--- a/fs/ntfs3/frecord.c
+++ b/fs/ntfs3/frecord.c
@@ -236,6 +236,7 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, 
struct ATTRIB *attr,
      return attr;

  out:
+    ntfs_inode_err(&ni->vfs_inode, "failed to parse mft record");
      ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
      return NULL;
  }
@@ -1643,14 +1644,13 @@ int ni_delete_all(struct ntfs_inode *ni)
   * Return: File name attribute by its value.
   */
  struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
-                     const struct cpu_str *uni,
+                     const struct le_str *uni,
                       const struct MFT_REF *home_dir,
                       struct mft_inode **mi,
                       struct ATTR_LIST_ENTRY **le)
  {
      struct ATTRIB *attr = NULL;
      struct ATTR_FILE_NAME *fname;
-    struct le_str *fns;

      if (le)
          *le = NULL;
@@ -1674,10 +1674,9 @@ struct ATTR_FILE_NAME *ni_fname_name(struct 
ntfs_inode *ni,
      if (uni->len != fname->name_len)
          goto next;

-    fns = (struct le_str *)&fname->name_len;
-    if (ntfs_cmp_names_cpu(uni, fns, NULL, false))
+    if (ntfs_cmp_names(uni->name, uni->len, fname->name, uni->len, NULL,
+               false))
          goto next;
-
      return fname;
  }

@@ -2915,7 +2914,7 @@ int ni_remove_name(struct ntfs_inode *dir_ni, 
struct ntfs_inode *ni,
      /* Find name in record. */
      mi_get_ref(&dir_ni->mi, &de_name->home);

-    fname = ni_fname_name(ni, (struct cpu_str *)&de_name->name_len,
+    fname = ni_fname_name(ni, (struct le_str *)&de_name->name_len,
                    &de_name->home, &mi, &le);
      if (!fname)
          return -ENOENT;
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 98b61e4b3215..00fa782fcada 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -543,7 +543,7 @@ void ni_remove_attr_le(struct ntfs_inode *ni, struct 
ATTRIB *attr,
                 struct mft_inode *mi, struct ATTR_LIST_ENTRY *le);
  int ni_delete_all(struct ntfs_inode *ni);
  struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
-                     const struct cpu_str *uni,
+                     const struct le_str *uni,
                       const struct MFT_REF *home,
                       struct mft_inode **mi,
                       struct ATTR_LIST_ENTRY **entry);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/10] fs/ntfs3: Add support /proc/fs/ntfs3/<dev>/volinfo and /proc/fs/ntfs3/<dev>/label
  2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
                   ` (8 preceding siblings ...)
  2023-05-08 12:39 ` [PATCH 09/10] fs/ntfs3: Fix endian problem Konstantin Komarov
@ 2023-05-08 12:40 ` Konstantin Komarov
  9 siblings, 0 replies; 11+ messages in thread
From: Konstantin Komarov @ 2023-05-08 12:40 UTC (permalink / raw)
  To: ntfs3; +Cc: Linux Kernel Mailing List, linux-fsdevel

Metafile /proc/fs/ntfs3/<dev>/label allows to read/write current ntfs label.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/fsntfs.c  |  58 ++++++++++++++++++++
  fs/ntfs3/ntfs_fs.h |   5 +-
  fs/ntfs3/super.c   | 134 +++++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 195 insertions(+), 2 deletions(-)

diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
index 1c05c088d1c6..33afee0f5559 100644
--- a/fs/ntfs3/fsntfs.c
+++ b/fs/ntfs3/fsntfs.c
@@ -9,6 +9,7 @@
  #include <linux/buffer_head.h>
  #include <linux/fs.h>
  #include <linux/kernel.h>
+#include <linux/nls.h>

  #include "debug.h"
  #include "ntfs.h"
@@ -2619,3 +2620,60 @@ bool valid_windows_name(struct ntfs_sb_info *sbi, 
const struct le_str *fname)
      return !name_has_forbidden_chars(fname) &&
             !is_reserved_name(sbi, fname);
  }
+
+/*
+ * ntfs_set_label - updates current ntfs label.
+ */
+int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len)
+{
+    int err;
+    struct ATTRIB *attr;
+    struct ntfs_inode *ni = sbi->volume.ni;
+    const u8 max_ulen = 0x80; /* TODO: use attrdef to get maximum length */
+    /* Allocate PATH_MAX bytes. */
+    struct cpu_str *uni = __getname();
+
+    if (!uni)
+        return -ENOMEM;
+
+    err = ntfs_nls_to_utf16(sbi, label, len, uni, (PATH_MAX - 2) / 2,
+                UTF16_LITTLE_ENDIAN);
+    if (err < 0)
+        goto out;
+
+    if (uni->len > max_ulen) {
+        ntfs_warn(sbi->sb, "new label is too long");
+        err = -EFBIG;
+        goto out;
+    }
+
+    ni_lock(ni);
+
+    /* Ignore any errors. */
+    ni_remove_attr(ni, ATTR_LABEL, NULL, 0, false, NULL);
+
+    err = ni_insert_resident(ni, uni->len * sizeof(u16), ATTR_LABEL, NULL,
+                 0, &attr, NULL, NULL);
+    if (err < 0)
+        goto unlock_out;
+
+    /* write new label in on-disk struct. */
+    memcpy(resident_data(attr), uni->name, uni->len * sizeof(u16));
+
+    /* update cached value of current label. */
+    if (len >= ARRAY_SIZE(sbi->volume.label))
+        len = ARRAY_SIZE(sbi->volume.label) - 1;
+    memcpy(sbi->volume.label, label, len);
+    sbi->volume.label[len] = 0;
+    mark_inode_dirty_sync(&ni->vfs_inode);
+
+unlock_out:
+    ni_unlock(ni);
+
+    if (!err)
+        err = _ni_write_inode(&ni->vfs_inode, 0);
+
+out:
+    __putname(uni);
+    return err;
+}
\ No newline at end of file
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 00fa782fcada..629403ede6e5 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -276,7 +276,7 @@ struct ntfs_sb_info {
          __le16 flags; // Cached current VOLUME_INFO::flags, 
VOLUME_FLAG_DIRTY.
          u8 major_ver;
          u8 minor_ver;
-        char label[65];
+        char label[256];
          bool real_dirty; // Real fs state.
      } volume;

@@ -286,7 +286,6 @@ struct ntfs_sb_info {
          struct ntfs_inode *ni;
          u32 next_id;
          u64 next_off;
-
          __le32 def_security_id;
      } security;

@@ -314,6 +313,7 @@ struct ntfs_sb_info {

      struct ntfs_mount_options *options;
      struct ratelimit_state msg_ratelimit;
+    struct proc_dir_entry *procdir;
  };

  /* One MFT record(usually 1024 bytes), consists of attributes. */
@@ -651,6 +651,7 @@ void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST 
lcn, CLST len, bool trim);
  int run_deallocate(struct ntfs_sb_info *sbi, const struct runs_tree *run,
             bool trim);
  bool valid_windows_name(struct ntfs_sb_info *sbi, const struct le_str 
*name);
+int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len);

  /* Globals from index.c */
  int indx_used_bit(struct ntfs_index *indx, struct ntfs_inode *ni, 
size_t *bit);
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 7ab0a79c7d84..e36769eac7de 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -57,6 +57,7 @@
  #include <linux/minmax.h>
  #include <linux/module.h>
  #include <linux/nls.h>
+#include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/statfs.h>

@@ -441,6 +442,103 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
      return 0;
  }

+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_info_root;
+
+/*
+ * ntfs3_volinfo:
+ *
+ * The content of /proc/fs/ntfs3/<dev>/volinfo
+ *
+ * ntfs3.1
+ * cluster size
+ * number of clusters
+*/
+static int ntfs3_volinfo(struct seq_file *m, void *o)
+{
+    struct super_block *sb = m->private;
+    struct ntfs_sb_info *sbi = sb->s_fs_info;
+
+    seq_printf(m, "ntfs%d.%d\n%u\n%zu\n", sbi->volume.major_ver,
+           sbi->volume.minor_ver, sbi->cluster_size,
+           sbi->used.bitmap.nbits);
+
+    return 0;
+}
+
+static int ntfs3_volinfo_open(struct inode *inode, struct file *file)
+{
+    return single_open(file, ntfs3_volinfo, pde_data(inode));
+}
+
+/* read /proc/fs/ntfs3/<dev>/label */
+static int ntfs3_label_show(struct seq_file *m, void *o)
+{
+    struct super_block *sb = m->private;
+    struct ntfs_sb_info *sbi = sb->s_fs_info;
+
+    seq_printf(m, "%s\n", sbi->volume.label);
+
+    return 0;
+}
+
+/* write /proc/fs/ntfs3/<dev>/label */
+static ssize_t ntfs3_label_write(struct file *file, const char __user 
*buffer,
+                 size_t count, loff_t *ppos)
+{
+    int err;
+    struct super_block *sb = pde_data(file_inode(file));
+    struct ntfs_sb_info *sbi = sb->s_fs_info;
+    ssize_t ret = count;
+    u8 *label = kmalloc(count, GFP_NOFS);
+
+    if (!label)
+        return -ENOMEM;
+
+    if (copy_from_user(label, buffer, ret)) {
+        ret = -EFAULT;
+        goto out;
+    }
+    while (ret > 0 && label[ret - 1] == '\n')
+        ret -= 1;
+
+    err = ntfs_set_label(sbi, label, ret);
+
+    if (err < 0) {
+        ntfs_err(sb, "failed (%d) to write label", err);
+        ret = err;
+        goto out;
+    }
+
+    *ppos += count;
+    ret = count;
+out:
+    kfree(label);
+    return ret;
+}
+
+static int ntfs3_label_open(struct inode *inode, struct file *file)
+{
+    return single_open(file, ntfs3_label_show, pde_data(inode));
+}
+
+static const struct proc_ops ntfs3_volinfo_fops = {
+    .proc_read = seq_read,
+    .proc_lseek = seq_lseek,
+    .proc_release = single_release,
+    .proc_open = ntfs3_volinfo_open,
+};
+
+static const struct proc_ops ntfs3_label_fops = {
+    .proc_read = seq_read,
+    .proc_lseek = seq_lseek,
+    .proc_release = single_release,
+    .proc_open = ntfs3_label_open,
+    .proc_write = ntfs3_label_write,
+};
+
+#endif
+
  static struct kmem_cache *ntfs_inode_cachep;

  static struct inode *ntfs_alloc_inode(struct super_block *sb)
@@ -515,6 +613,16 @@ static void ntfs_put_super(struct super_block *sb)
  {
      struct ntfs_sb_info *sbi = sb->s_fs_info;

+#ifdef CONFIG_PROC_FS
+    // Remove /proc/fs/ntfs3/..
+    if (sbi->procdir) {
+        remove_proc_entry("label", sbi->procdir);
+        remove_proc_entry("volinfo", sbi->procdir);
+        remove_proc_entry(sb->s_id, proc_info_root);
+        sbi->procdir = NULL;
+    }
+#endif
+
      /* Mark rw ntfs as clear, if possible. */
      ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);

@@ -1436,6 +1544,20 @@ static int ntfs_fill_super(struct super_block 
*sb, struct fs_context *fc)
          kfree(boot2);
      }

+#ifdef CONFIG_PROC_FS
+    /* Create /proc/fs/ntfs3/.. */
+    if (proc_info_root) {
+        struct proc_dir_entry *e = proc_mkdir(sb->s_id, proc_info_root);
+        if (e) {
+            proc_create_data("volinfo", S_IFREG | S_IRUGO, e,
+                     &ntfs3_volinfo_fops, sb);
+            proc_create_data("label", S_IFREG | S_IRUGO | S_IWUGO,
+                     e, &ntfs3_label_fops, sb);
+            sbi->procdir = e;
+        }
+    }
+#endif
+
      return 0;

  put_inode_out:
@@ -1630,6 +1752,12 @@ static int __init init_ntfs_fs(void)
      if (IS_ENABLED(CONFIG_NTFS3_LZX_XPRESS))
          pr_info("ntfs3: Read-only LZX/Xpress compression included\n");

+
+#ifdef CONFIG_PROC_FS
+    /* Create "/proc/fs/ntfs3" */
+    proc_info_root = proc_mkdir("fs/ntfs3", NULL);
+#endif
+
      err = ntfs3_init_bitmap();
      if (err)
          return err;
@@ -1661,6 +1789,12 @@ static void __exit exit_ntfs_fs(void)
      kmem_cache_destroy(ntfs_inode_cachep);
      unregister_filesystem(&ntfs_fs_type);
      ntfs3_exit_bitmap();
+
+#ifdef CONFIG_PROC_FS
+    if (proc_info_root)
+        remove_proc_entry("fs/ntfs3", NULL);
+#endif
+
  }

  MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2023-05-08 12:40 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-08 12:35 [PATCH 00/10] Refactoring and bugfix Konstantin Komarov
2023-05-08 12:36 ` [PATCH 01/10] fs/ntfs3: Correct checking while generating attr_list Konstantin Komarov
2023-05-08 12:36 ` [PATCH 02/10] fs/ntfs3: Fix ntfs_atomic_open Konstantin Komarov
2023-05-08 12:36 ` [PATCH 03/10] fs/ntfs3: Mark ntfs dirty when on-disk struct is corrupted Konstantin Komarov
2023-05-08 12:37 ` [PATCH 04/10] fs/ntfs3: Alternative boot if primary boot " Konstantin Komarov
2023-05-08 12:38 ` [PATCH 05/10] fs/ntfs3: Do not update primary boot in ntfs_init_from_boot() Konstantin Komarov
2023-05-08 12:38 ` [PATCH 06/10] fs/ntfs3: Code formatting Konstantin Komarov
2023-05-08 12:38 ` [PATCH 07/10] fs/ntfs3: Code refactoring Konstantin Komarov
2023-05-08 12:39 ` [PATCH 08/10] fs/ntfs3: Add ability to format new mft records with bigger/smaller header Konstantin Komarov
2023-05-08 12:39 ` [PATCH 09/10] fs/ntfs3: Fix endian problem Konstantin Komarov
2023-05-08 12:40 ` [PATCH 10/10] fs/ntfs3: Add support /proc/fs/ntfs3/<dev>/volinfo and /proc/fs/ntfs3/<dev>/label Konstantin Komarov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).