diff options
author | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2021-08-31 18:52:39 +0300 |
---|---|---|
committer | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2021-08-31 19:07:11 +0300 |
commit | 78ab59fee07f22464f32eafebab2bd97ba94ff2d (patch) | |
tree | 8c906238a8ffbc639ce1911295f6e961e6212f6e /fs/ntfs3/attrlist.c | |
parent | a97131c29c997e81b6fa1d1adf8f3ca07b63a2e1 (diff) | |
download | linux-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.c | 26 |
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; } |