Skip to content

Commit 2d5eb50

Browse files
dubeykogregkh
authored andcommitted
hfs: clear offset and space out of valid records in b-tree node
[ Upstream commit 18b07c4 ] Currently, hfs_brec_remove() executes moving records towards the location of deleted record and it updates offsets of moved records. However, the hfs_brec_remove() logic ignores the "mess" of b-tree node's free space and it doesn't touch the offsets out of records number. Potentially, it could confuse fsck or driver logic or to be a reason of potential corruption cases. This patch reworks the logic of hfs_brec_remove() by means of clearing freed space of b-tree node after the records moving. And it clear the last offset that keeping old location of free space because now the offset before this one is keeping the actual offset to the free space after the record deletion. Signed-off-by: Viacheslav Dubeyko <[email protected]> cc: John Paul Adrian Glaubitz <[email protected]> cc: Yangtao Li <[email protected]> cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Viacheslav Dubeyko <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 90f5f71 commit 2d5eb50

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

fs/hfs/brec.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ int hfs_brec_remove(struct hfs_find_data *fd)
179179
struct hfs_btree *tree;
180180
struct hfs_bnode *node, *parent;
181181
int end_off, rec_off, data_off, size;
182+
int src, dst, len;
182183

183184
tree = fd->tree;
184185
node = fd->bnode;
@@ -208,20 +209,38 @@ int hfs_brec_remove(struct hfs_find_data *fd)
208209
}
209210
hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
210211

211-
if (rec_off == end_off)
212-
goto skip;
213212
size = fd->keylength + fd->entrylength;
214213

214+
if (rec_off == end_off) {
215+
src = fd->keyoffset;
216+
hfs_bnode_clear(node, src, size);
217+
goto skip;
218+
}
219+
215220
do {
216221
data_off = hfs_bnode_read_u16(node, rec_off);
217222
hfs_bnode_write_u16(node, rec_off + 2, data_off - size);
218223
rec_off -= 2;
219224
} while (rec_off >= end_off);
220225

221226
/* fill hole */
222-
hfs_bnode_move(node, fd->keyoffset, fd->keyoffset + size,
223-
data_off - fd->keyoffset - size);
227+
dst = fd->keyoffset;
228+
src = fd->keyoffset + size;
229+
len = data_off - src;
230+
231+
hfs_bnode_move(node, dst, src, len);
232+
233+
src = dst + len;
234+
len = data_off - src;
235+
236+
hfs_bnode_clear(node, src, len);
237+
224238
skip:
239+
/*
240+
* Remove the obsolete offset to free space.
241+
*/
242+
hfs_bnode_write_u16(node, end_off, 0);
243+
225244
hfs_bnode_dump(node);
226245
if (!fd->record)
227246
hfs_brec_update_parent(fd);

0 commit comments

Comments
 (0)