mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
hfs: clear offset and space out of valid records in b-tree node
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 <slava@dubeyko.com> cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> cc: Yangtao Li <frank.li@vivo.com> cc: linux-fsdevel@vger.kernel.org Link: https://lore.kernel.org/r/20250815194918.38165-1-slava@dubeyko.com Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
This commit is contained in:
@@ -179,6 +179,7 @@ int hfs_brec_remove(struct hfs_find_data *fd)
|
|||||||
struct hfs_btree *tree;
|
struct hfs_btree *tree;
|
||||||
struct hfs_bnode *node, *parent;
|
struct hfs_bnode *node, *parent;
|
||||||
int end_off, rec_off, data_off, size;
|
int end_off, rec_off, data_off, size;
|
||||||
|
int src, dst, len;
|
||||||
|
|
||||||
tree = fd->tree;
|
tree = fd->tree;
|
||||||
node = fd->bnode;
|
node = fd->bnode;
|
||||||
@@ -208,10 +209,14 @@ again:
|
|||||||
}
|
}
|
||||||
hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
|
hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
|
||||||
|
|
||||||
if (rec_off == end_off)
|
|
||||||
goto skip;
|
|
||||||
size = fd->keylength + fd->entrylength;
|
size = fd->keylength + fd->entrylength;
|
||||||
|
|
||||||
|
if (rec_off == end_off) {
|
||||||
|
src = fd->keyoffset;
|
||||||
|
hfs_bnode_clear(node, src, size);
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
data_off = hfs_bnode_read_u16(node, rec_off);
|
data_off = hfs_bnode_read_u16(node, rec_off);
|
||||||
hfs_bnode_write_u16(node, rec_off + 2, data_off - size);
|
hfs_bnode_write_u16(node, rec_off + 2, data_off - size);
|
||||||
@@ -219,9 +224,23 @@ again:
|
|||||||
} while (rec_off >= end_off);
|
} while (rec_off >= end_off);
|
||||||
|
|
||||||
/* fill hole */
|
/* fill hole */
|
||||||
hfs_bnode_move(node, fd->keyoffset, fd->keyoffset + size,
|
dst = fd->keyoffset;
|
||||||
data_off - fd->keyoffset - size);
|
src = fd->keyoffset + size;
|
||||||
|
len = data_off - src;
|
||||||
|
|
||||||
|
hfs_bnode_move(node, dst, src, len);
|
||||||
|
|
||||||
|
src = dst + len;
|
||||||
|
len = data_off - src;
|
||||||
|
|
||||||
|
hfs_bnode_clear(node, src, len);
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
|
/*
|
||||||
|
* Remove the obsolete offset to free space.
|
||||||
|
*/
|
||||||
|
hfs_bnode_write_u16(node, end_off, 0);
|
||||||
|
|
||||||
hfs_bnode_dump(node);
|
hfs_bnode_dump(node);
|
||||||
if (!fd->record)
|
if (!fd->record)
|
||||||
hfs_brec_update_parent(fd);
|
hfs_brec_update_parent(fd);
|
||||||
|
|||||||
Reference in New Issue
Block a user