Commit ddc19e6e authored by Al Viro's avatar Al Viro

hpfs: annotate btree nodes, get rid of bitfields mess

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 39413c60
...@@ -20,7 +20,7 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode, ...@@ -20,7 +20,7 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
int c1, c2 = 0; int c1, c2 = 0;
go_down: go_down:
if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1; if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
if (btree->internal) { if (bp_internal(btree)) {
for (i = 0; i < btree->n_used_nodes; i++) for (i = 0; i < btree->n_used_nodes; i++)
if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) { if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
a = le32_to_cpu(btree->u.internal[i].down); a = le32_to_cpu(btree->u.internal[i].down);
...@@ -82,7 +82,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi ...@@ -82,7 +82,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
brelse(bh); brelse(bh);
return -1; return -1;
} }
if (btree->internal) { if (bp_internal(btree)) {
a = le32_to_cpu(btree->u.internal[n].down); a = le32_to_cpu(btree->u.internal[n].down);
btree->u.internal[n].file_secno = cpu_to_le32(-1); btree->u.internal[n].file_secno = cpu_to_le32(-1);
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
...@@ -129,12 +129,12 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi ...@@ -129,12 +129,12 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
} }
if (a == node && fnod) { if (a == node && fnod) {
anode->up = cpu_to_le32(node); anode->up = cpu_to_le32(node);
anode->btree.fnode_parent = 1; anode->btree.flags |= BP_fnode_parent;
anode->btree.n_used_nodes = btree->n_used_nodes; anode->btree.n_used_nodes = btree->n_used_nodes;
anode->btree.first_free = btree->first_free; anode->btree.first_free = btree->first_free;
anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes; anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes;
memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12); memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12);
btree->internal = 1; btree->flags |= BP_internal;
btree->n_free_nodes = 11; btree->n_free_nodes = 11;
btree->n_used_nodes = 1; btree->n_used_nodes = 1;
btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree); btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree);
...@@ -184,7 +184,10 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi ...@@ -184,7 +184,10 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
hpfs_free_sectors(s, ra, 1); hpfs_free_sectors(s, ra, 1);
if ((anode = hpfs_map_anode(s, na, &bh))) { if ((anode = hpfs_map_anode(s, na, &bh))) {
anode->up = cpu_to_le32(up); anode->up = cpu_to_le32(up);
anode->btree.fnode_parent = up == node && fnod; if (up == node && fnod)
anode->btree.flags |= BP_fnode_parent;
else
anode->btree.flags &= ~BP_fnode_parent;
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
brelse(bh); brelse(bh);
} }
...@@ -198,7 +201,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi ...@@ -198,7 +201,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) { if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) {
anode = new_anode; anode = new_anode;
/*anode->up = cpu_to_le32(up != -1 ? up : ra);*/ /*anode->up = cpu_to_le32(up != -1 ? up : ra);*/
anode->btree.internal = 1; anode->btree.flags |= BP_internal;
anode->btree.n_used_nodes = 1; anode->btree.n_used_nodes = 1;
anode->btree.n_free_nodes = 59; anode->btree.n_free_nodes = 59;
anode->btree.first_free = cpu_to_le16(16); anode->btree.first_free = cpu_to_le16(16);
...@@ -215,7 +218,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi ...@@ -215,7 +218,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
} }
if ((anode = hpfs_map_anode(s, na, &bh))) { if ((anode = hpfs_map_anode(s, na, &bh))) {
anode->up = cpu_to_le32(node); anode->up = cpu_to_le32(node);
if (fnod) anode->btree.fnode_parent = 1; if (fnod)
anode->btree.flags |= BP_fnode_parent;
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
brelse(bh); brelse(bh);
} }
...@@ -234,18 +238,19 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi ...@@ -234,18 +238,19 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
} }
ranode->up = cpu_to_le32(node); ranode->up = cpu_to_le32(node);
memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free)); memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
if (fnod) ranode->btree.fnode_parent = 1; if (fnod)
ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes; ranode->btree.flags |= BP_fnode_parent;
if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) { ranode->btree.n_free_nodes = (bp_internal(&ranode->btree) ? 60 : 40) - ranode->btree.n_used_nodes;
if (bp_internal(&ranode->btree)) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
struct anode *unode; struct anode *unode;
if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) { if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
unode->up = cpu_to_le32(ra); unode->up = cpu_to_le32(ra);
unode->btree.fnode_parent = 0; unode->btree.flags &= ~BP_fnode_parent;
mark_buffer_dirty(bh1); mark_buffer_dirty(bh1);
brelse(bh1); brelse(bh1);
} }
} }
btree->internal = 1; btree->flags |= BP_internal;
btree->n_free_nodes = fnod ? 10 : 58; btree->n_free_nodes = fnod ? 10 : 58;
btree->n_used_nodes = 2; btree->n_used_nodes = 2;
btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree); btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree);
...@@ -278,7 +283,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree) ...@@ -278,7 +283,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
int d1, d2; int d1, d2;
go_down: go_down:
d2 = 0; d2 = 0;
while (btree1->internal) { while (bp_internal(btree1)) {
ano = le32_to_cpu(btree1->u.internal[pos].down); ano = le32_to_cpu(btree1->u.internal[pos].down);
if (level) brelse(bh); if (level) brelse(bh);
if (hpfs_sb(s)->sb_chk) if (hpfs_sb(s)->sb_chk)
...@@ -412,13 +417,13 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) ...@@ -412,13 +417,13 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
btree->n_free_nodes = 8; btree->n_free_nodes = 8;
btree->n_used_nodes = 0; btree->n_used_nodes = 0;
btree->first_free = cpu_to_le16(8); btree->first_free = cpu_to_le16(8);
btree->internal = 0; btree->flags &= ~BP_internal;
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
} else hpfs_free_sectors(s, f, 1); } else hpfs_free_sectors(s, f, 1);
brelse(bh); brelse(bh);
return; return;
} }
while (btree->internal) { while (bp_internal(btree)) {
nodes = btree->n_used_nodes + btree->n_free_nodes; nodes = btree->n_used_nodes + btree->n_free_nodes;
for (i = 0; i < btree->n_used_nodes; i++) for (i = 0; i < btree->n_used_nodes; i++)
if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f; if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;
......
...@@ -375,50 +375,36 @@ struct hpfs_dirent { ...@@ -375,50 +375,36 @@ struct hpfs_dirent {
struct bplus_leaf_node struct bplus_leaf_node
{ {
u32 file_secno; /* first file sector in extent */ __le32 file_secno; /* first file sector in extent */
u32 length; /* length, sectors */ __le32 length; /* length, sectors */
secno disk_secno; /* first corresponding disk sector */ __le32 disk_secno; /* first corresponding disk sector */
}; };
struct bplus_internal_node struct bplus_internal_node
{ {
u32 file_secno; /* subtree maps sectors < this */ __le32 file_secno; /* subtree maps sectors < this */
anode_secno down; /* pointer to subtree */ __le32 down; /* pointer to subtree */
}; };
enum {
BP_hbff = 1,
BP_fnode_parent = 0x20,
BP_binary_search = 0x40,
BP_internal = 0x80
};
struct bplus_header struct bplus_header
{ {
#ifdef __LITTLE_ENDIAN u8 flags; /* bit 0 - high bit of first free entry offset
u8 hbff: 1; /* high bit of first free entry offset */ bit 5 - we're pointed to by an fnode,
u8 flag1234: 4;
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
the data btree or some ea or the the data btree or some ea or the
main ea bootage pointer ea_secno */ main ea bootage pointer ea_secno
/* also can get set in fnodes, which bit 6 - suggest binary search (unused)
may be a chkdsk glitch or may mean bit 7 - 1 -> (internal) tree of anodes
this bit is irrelevant in fnodes,
or this interpretation is all wet */
u8 binary_search: 1; /* suggest binary search (unused) */
u8 internal: 1; /* 1 -> (internal) tree of anodes
0 -> (leaf) list of extents */
#else
u8 internal: 1; /* 1 -> (internal) tree of anodes
0 -> (leaf) list of extents */ 0 -> (leaf) list of extents */
u8 binary_search: 1; /* suggest binary search (unused) */
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
the data btree or some ea or the
main ea bootage pointer ea_secno */
/* also can get set in fnodes, which
may be a chkdsk glitch or may mean
this bit is irrelevant in fnodes,
or this interpretation is all wet */
u8 flag1234: 4;
u8 hbff: 1; /* high bit of first free entry offset */
#endif
u8 fill[3]; u8 fill[3];
u8 n_free_nodes; /* free nodes in following array */ u8 n_free_nodes; /* free nodes in following array */
u8 n_used_nodes; /* used nodes in following array */ u8 n_used_nodes; /* used nodes in following array */
u16 first_free; /* offset from start of header to __le16 first_free; /* offset from start of header to
first free node in array */ first free node in array */
union { union {
struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
...@@ -428,6 +414,16 @@ struct bplus_header ...@@ -428,6 +414,16 @@ struct bplus_header
} u; } u;
}; };
static inline bool bp_internal(struct bplus_header *bp)
{
return bp->flags & BP_internal;
}
static inline bool bp_fnode_parent(struct bplus_header *bp)
{
return bp->flags & BP_fnode_parent;
}
/* fnode: root of allocation b+ tree, and EA's */ /* fnode: root of allocation b+ tree, and EA's */
/* Every file and every directory has one fnode, pointed to by the directory /* Every file and every directory has one fnode, pointed to by the directory
......
...@@ -132,14 +132,14 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea ...@@ -132,14 +132,14 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
} }
if (!fnode_is_dir(fnode)) { if (!fnode_is_dir(fnode)) {
if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes != if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes !=
(fnode->btree.internal ? 12 : 8)) { (bp_internal(&fnode->btree) ? 12 : 8)) {
hpfs_error(s, hpfs_error(s,
"bad number of nodes in fnode %08lx", "bad number of nodes in fnode %08lx",
(unsigned long)ino); (unsigned long)ino);
goto bail; goto bail;
} }
if (le16_to_cpu(fnode->btree.first_free) != if (le16_to_cpu(fnode->btree.first_free) !=
8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { 8 + fnode->btree.n_used_nodes * (bp_internal(&fnode->btree) ? 8 : 12)) {
hpfs_error(s, hpfs_error(s,
"bad first_free pointer in fnode %08lx", "bad first_free pointer in fnode %08lx",
(unsigned long)ino); (unsigned long)ino);
...@@ -187,12 +187,12 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff ...@@ -187,12 +187,12 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
goto bail; goto bail;
} }
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
(anode->btree.internal ? 60 : 40)) { (bp_internal(&anode->btree) ? 60 : 40)) {
hpfs_error(s, "bad number of nodes in anode %08x", ano); hpfs_error(s, "bad number of nodes in anode %08x", ano);
goto bail; goto bail;
} }
if (le16_to_cpu(anode->btree.first_free) != if (le16_to_cpu(anode->btree.first_free) !=
8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { 8 + anode->btree.n_used_nodes * (bp_internal(&anode->btree) ? 8 : 12)) {
hpfs_error(s, "bad first_free pointer in anode %08x", ano); hpfs_error(s, "bad first_free pointer in anode %08x", ano);
goto bail; goto bail;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment