summaryrefslogtreecommitdiff
path: root/fs/ntfs3/attrlist.c
diff options
context:
space:
mode:
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;
}