From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
To: <ntfs3@lists.linux.dev>
Cc: <linux-kernel@vger.kernel.org>, <linux-fsdevel@vger.kernel.org>
Subject: [PATCH 4/6] fs/ntfs3: Refactoring attr_insert_range to restore after errors
Date: Wed, 13 Jul 2022 19:46:38 +0300 [thread overview]
Message-ID: <ab84cf8a-63bc-fc54-9f0c-43b3ef2705ab@paragon-software.com> (raw)
In-Reply-To: <2101d95b-be41-6e6d-e019-bc70f816b2e8@paragon-software.com>
Added done and undo labels for restoring after errors
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
fs/ntfs3/attrib.c | 115 ++++++++++++++++++++++++++++++++++------------
1 file changed, 86 insertions(+), 29 deletions(-)
diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
index 24d545041787..71f870d497ae 100644
--- a/fs/ntfs3/attrib.c
+++ b/fs/ntfs3/attrib.c
@@ -2275,28 +2275,29 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
if (!attr_b->non_res) {
err = attr_set_size(ni, ATTR_DATA, NULL, 0, run,
- data_size + bytes, NULL, false, &attr);
+ data_size + bytes, NULL, false, NULL);
+
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL,
+ &mi_b);
+ if (!attr_b) {
+ err = -EINVAL;
+ goto bad_inode;
+ }
+
if (err)
goto out;
- if (!attr->non_res) {
+
+ if (!attr_b->non_res) {
/* Still resident. */
- char *data = Add2Ptr(attr, attr->res.data_off);
+ char *data = Add2Ptr(attr_b, attr_b->res.data_off);
memmove(data + bytes, data, bytes);
memset(data, 0, bytes);
- err = 0;
- goto out;
+ goto done;
}
+
/* Resident files becomes nonresident. */
- le_b = NULL;
- attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL,
- &mi_b);
- if (!attr_b)
- return -ENOENT;
- if (!attr_b->non_res) {
- err = -EINVAL;
- goto out;
- }
data_size = le64_to_cpu(attr_b->nres.data_size);
alloc_size = le64_to_cpu(attr_b->nres.alloc_size);
}
@@ -2314,14 +2315,14 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
mi = mi_b;
} else if (!le_b) {
err = -EINVAL;
- goto out;
+ goto bad_inode;
} else {
le = le_b;
attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
&mi);
if (!attr) {
err = -EINVAL;
- goto out;
+ goto bad_inode;
}
svcn = le64_to_cpu(attr->nres.svcn);
@@ -2344,7 +2345,6 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
goto out;
next_svcn = le64_to_cpu(attr->nres.evcn) + 1;
- run_truncate_head(run, next_svcn);
while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi)) &&
attr->type == ATTR_DATA && !attr->name_len) {
@@ -2357,9 +2357,27 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
mi->dirty = true;
}
+ if (next_svcn < evcn1 + len) {
+ err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run,
+ next_svcn, evcn1 + len - next_svcn,
+ a_flags, NULL, NULL, NULL);
+
+ le_b = NULL;
+ attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL,
+ &mi_b);
+ if (!attr_b) {
+ err = -EINVAL;
+ goto bad_inode;
+ }
+
+ if (err) {
+ /* ni_insert_nonresident failed. Try to undo. */
+ goto undo_insert_range;
+ }
+ }
+
/*
- * Update primary attribute segment in advance.
- * pointer attr_b may become invalid (layout of mft is changed)
+ * Update primary attribute segment.
*/
if (vbo <= ni->i_valid)
ni->i_valid += bytes;
@@ -2374,14 +2392,7 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
attr_b->nres.valid_size = cpu_to_le64(ni->i_valid);
mi_b->dirty = true;
- if (next_svcn < evcn1 + len) {
- err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run,
- next_svcn, evcn1 + len - next_svcn,
- a_flags, NULL, NULL, NULL);
- if (err)
- goto out;
- }
-
+done:
ni->vfs_inode.i_size += bytes;
ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
mark_inode_dirty(&ni->vfs_inode);
@@ -2390,8 +2401,54 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
run_truncate(run, 0); /* clear cached values. */
up_write(&ni->file.run_lock);
- if (err)
- _ntfs_bad_inode(&ni->vfs_inode);
return err;
+
+bad_inode:
+ _ntfs_bad_inode(&ni->vfs_inode);
+ goto out;
+
+undo_insert_range:
+ svcn = le64_to_cpu(attr_b->nres.svcn);
+ evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
+
+ if (svcn <= vcn && vcn < evcn1) {
+ attr = attr_b;
+ le = le_b;
+ mi = mi_b;
+ } else if (!le_b) {
+ goto bad_inode;
+ } else {
+ le = le_b;
+ attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn,
+ &mi);
+ if (!attr) {
+ goto bad_inode;
+ }
+
+ svcn = le64_to_cpu(attr->nres.svcn);
+ evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
+ }
+
+ if (attr_load_runs(attr, ni, run, NULL))
+ goto bad_inode;
+
+ if (!run_collapse_range(run, vcn, len))
+ goto bad_inode;
+
+ if (mi_pack_runs(mi, attr, run, evcn1 + len - svcn))
+ goto bad_inode;
+
+ while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi)) &&
+ attr->type == ATTR_DATA && !attr->name_len) {
+ le64_sub_cpu(&attr->nres.svcn, len);
+ le64_sub_cpu(&attr->nres.evcn, len);
+ if (le) {
+ le->vcn = attr->nres.svcn;
+ ni->attr_list.dirty = true;
+ }
+ mi->dirty = true;
+ }
+
+ goto out;
}
--
2.37.0
next prev parent reply other threads:[~2022-07-13 16:47 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-13 16:44 [PATCH 0/6] fs/ntfs3: Refactoring of several functions Konstantin Komarov
2022-07-13 16:45 ` [PATCH 1/6] fs/ntfs3: New function ntfs_bad_inode Konstantin Komarov
2022-07-13 16:45 ` [PATCH 2/6] fs/ntfs3: Refactoring attr_set_size to restore after errors Konstantin Komarov
2022-07-13 16:46 ` [PATCH 3/6] fs/ntfs3: Refactoring attr_punch_hole " Konstantin Komarov
2022-07-13 18:58 ` Joe Perches
2022-07-13 16:46 ` Konstantin Komarov [this message]
2022-07-13 16:47 ` [PATCH 5/6] fs/ntfs3: Create MFT zone only if length is large enough Konstantin Komarov
2022-07-13 16:47 ` [PATCH 6/6] fs/ntfs3: Make ni_ins_new_attr return error Konstantin Komarov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ab84cf8a-63bc-fc54-9f0c-43b3ef2705ab@paragon-software.com \
--to=almaz.alexandrovich@paragon-software.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ntfs3@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®