diff mbox series

[08/11] fs/ntfs3: Always make file nonresident if fallocate (xfstest 438)

Message ID de201466-f50e-4a99-a483-9374661e480d@paragon-software.com (mailing list archive)
State New
Headers show
Series Bugfix and refactoring | expand

Commit Message

Konstantin Komarov April 17, 2024, 1:08 p.m. UTC
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/attrib.c  | 32 ++++++++++++++++++++++++++++++++
  fs/ntfs3/file.c    |  9 +++++++++
  fs/ntfs3/ntfs_fs.h |  1 +
  3 files changed, 42 insertions(+)

  /* Functions from attrlist.c */
  void al_destroy(struct ntfs_inode *ni);
diff mbox series

Patch

diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
index 7aadf5010999..aedae36b91d0 100644
--- a/fs/ntfs3/attrib.c
+++ b/fs/ntfs3/attrib.c
@@ -2558,3 +2558,35 @@  int attr_insert_range(struct ntfs_inode *ni, u64 
vbo, u64 bytes)

      goto out;
  }
+
+/*
+ * attr_force_nonresident
+ *
+ * Convert default data attribute into non resident form.
+ */
+int attr_force_nonresident(struct ntfs_inode *ni)
+{
+    int err;
+    struct ATTRIB *attr;
+    struct ATTR_LIST_ENTRY *le = NULL;
+    struct mft_inode *mi;
+
+    attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi);
+    if (!attr) {
+        ntfs_bad_inode(&ni->vfs_inode, "no data attribute");
+        return -ENOENT;
+    }
+
+    if (attr->non_res) {
+        /* Already non resident. */
+        return 0;
+    }
+
+    down_write(&ni->file.run_lock);
+    err = attr_make_nonresident(ni, attr, le, mi,
+                    le32_to_cpu(attr->res.data_size),
+                    &ni->file.run, &attr, NULL);
+    up_write(&ni->file.run_lock);
+
+    return err;
+}
\ No newline at end of file
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index 5418662c80d8..fce8ea098d60 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -578,6 +578,15 @@  static long ntfs_fallocate(struct file *file, int 
mode, loff_t vbo, loff_t len)
          /* Check new size. */
          u8 cluster_bits = sbi->cluster_bits;

+        /* Be sure file is non resident. */
+        if (is_resident(ni)) {
+            ni_lock(ni);
+            err = attr_force_nonresident(ni);
+            ni_unlock(ni);
+            if (err)
+                goto out;
+        }
+
          /* generic/213: expected -ENOSPC instead of -EFBIG. */
          if (!is_supported_holes) {
              loff_t to_alloc = new_size - inode_get_bytes(inode);
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 3db6a61f61dc..00dec0ec5648 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -452,6 +452,7 @@  int attr_allocate_frame(struct ntfs_inode *ni, CLST 
frame, size_t compr_size,
  int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);
  int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);
  int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 
*frame_size);
+int attr_force_nonresident(struct ntfs_inode *ni);