summaryrefslogtreecommitdiff
path: root/fs/ntfs3/attrlist.c
diff options
context:
space:
mode:
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>2021-08-31 18:52:39 +0300
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>2021-08-31 19:07:11 +0300
commit78ab59fee07f22464f32eafebab2bd97ba94ff2d (patch)
tree8c906238a8ffbc639ce1911295f6e961e6212f6e /fs/ntfs3/attrlist.c
parenta97131c29c997e81b6fa1d1adf8f3ca07b63a2e1 (diff)
downloadlinux-78ab59fee07f22464f32eafebab2bd97ba94ff2d.tar.xz
fs/ntfs3: Rework file operations
Rename now works "Add new name and remove old name". "Remove old name and add new name" may result in bad inode if we can't add new name and then can't restore (add) old name. Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Diffstat (limited to 'fs/ntfs3/attrlist.c')
-rw-r--r--fs/ntfs3/attrlist.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c
index 32ca990af64b..fa32399eb517 100644
--- a/fs/ntfs3/attrlist.c
+++ b/fs/ntfs3/attrlist.c
@@ -279,7 +279,7 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
struct ATTR_LIST_ENTRY *le;
size_t off;
u16 sz;
- size_t asize, new_asize;
+ size_t asize, new_asize, old_size;
u64 new_size;
typeof(ni->attr_list) *al = &ni->attr_list;
@@ -287,8 +287,9 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
* Compute the size of the new 'le'
*/
sz = le_size(name_len);
- new_size = al->size + sz;
- asize = al_aligned(al->size);
+ old_size = al->size;
+ new_size = old_size + sz;
+ asize = al_aligned(old_size);
new_asize = al_aligned(new_size);
/* Scan forward to the point at which the new 'le' should be inserted. */
@@ -302,13 +303,14 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
return -ENOMEM;
memcpy(ptr, al->le, off);
- memcpy(Add2Ptr(ptr, off + sz), le, al->size - off);
+ memcpy(Add2Ptr(ptr, off + sz), le, old_size - off);
le = Add2Ptr(ptr, off);
kfree(al->le);
al->le = ptr;
} else {
- memmove(Add2Ptr(le, sz), le, al->size - off);
+ memmove(Add2Ptr(le, sz), le, old_size - off);
}
+ *new_le = le;
al->size = new_size;
@@ -321,23 +323,25 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
le->id = id;
memcpy(le->name, name, sizeof(short) * name_len);
- al->dirty = true;
-
err = attr_set_size(ni, ATTR_LIST, NULL, 0, &al->run, new_size,
&new_size, true, &attr);
- if (err)
+ if (err) {
+ /* Undo memmove above. */
+ memmove(le, Add2Ptr(le, sz), old_size - off);
+ al->size = old_size;
return err;
+ }
+
+ al->dirty = true;
if (attr && attr->non_res) {
err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le,
al->size);
if (err)
return err;
+ al->dirty = false;
}
- al->dirty = false;
- *new_le = le;
-
return 0;
}