Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddc19e6e authored by Al Viro's avatar Al Viro
Browse files

hpfs: annotate btree nodes, get rid of bitfields mess



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 39413c60
Loading
Loading
Loading
Loading
+20 −15
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
	int c1, c2 = 0;
	go_down:
	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++)
			if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
				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
		brelse(bh);
		return -1;
	}
	if (btree->internal) {
	if (bp_internal(btree)) {
		a = le32_to_cpu(btree->u.internal[n].down);
		btree->u.internal[n].file_secno = cpu_to_le32(-1);
		mark_buffer_dirty(bh);
@@ -129,12 +129,12 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
		}
		if (a == node && fnod) {
			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.first_free = btree->first_free;
			anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes;
			memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12);
			btree->internal = 1;
			btree->flags |= BP_internal;
			btree->n_free_nodes = 11;
			btree->n_used_nodes = 1;
			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
			hpfs_free_sectors(s, ra, 1);
			if ((anode = hpfs_map_anode(s, na, &bh))) {
				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);
				brelse(bh);
			}
@@ -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))) {
			anode = new_anode;
			/*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_free_nodes = 59;
			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
	}
	if ((anode = hpfs_map_anode(s, na, &bh))) {
		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);
		brelse(bh);
	}
@@ -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);
	memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
	if (fnod) ranode->btree.fnode_parent = 1;
	ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes;
	if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
	if (fnod)
		ranode->btree.flags |= BP_fnode_parent;
	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;
		if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
			unode->up = cpu_to_le32(ra);
			unode->btree.fnode_parent = 0;
			unode->btree.flags &= ~BP_fnode_parent;
			mark_buffer_dirty(bh1);
			brelse(bh1);
		}
	}
	btree->internal = 1;
	btree->flags |= BP_internal;
	btree->n_free_nodes = fnod ? 10 : 58;
	btree->n_used_nodes = 2;
	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)
	int d1, d2;
	go_down:
	d2 = 0;
	while (btree1->internal) {
	while (bp_internal(btree1)) {
		ano = le32_to_cpu(btree1->u.internal[pos].down);
		if (level) brelse(bh);
		if (hpfs_sb(s)->sb_chk)
@@ -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_used_nodes = 0;
			btree->first_free = cpu_to_le16(8);
			btree->internal = 0;
			btree->flags &= ~BP_internal;
			mark_buffer_dirty(bh);
		} else hpfs_free_sectors(s, f, 1);
		brelse(bh);
		return;
	}
	while (btree->internal) {
	while (bp_internal(btree)) {
		nodes = btree->n_used_nodes + btree->n_free_nodes;
		for (i = 0; i < btree->n_used_nodes; i++)
			if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;
+28 −32
Original line number Diff line number Diff line
@@ -375,50 +375,36 @@ struct hpfs_dirent {

struct bplus_leaf_node
{
  u32 file_secno;			/* first file sector in extent */
  u32 length;				/* length, sectors */
  secno disk_secno;			/* first corresponding disk sector */
  __le32 file_secno;			/* first file sector in extent */
  __le32 length;			/* length, sectors */
  __le32 disk_secno;			/* first corresponding disk sector */
};

struct bplus_internal_node
{
  u32 file_secno;			/* subtree maps sectors < this  */
  anode_secno down;			/* pointer to subtree */
  __le32 file_secno;			/* subtree maps sectors < this  */
  __le32 down;				/* pointer to subtree */
};

enum {
	BP_hbff = 1,
	BP_fnode_parent = 0x20,
	BP_binary_search = 0x40,
	BP_internal = 0x80
};
struct bplus_header
{
#ifdef __LITTLE_ENDIAN
  u8 hbff: 1;			/* high bit of first free entry offset */
  u8 flag1234: 4;
  u8 fnode_parent: 1;			/* ? we're pointed to by an fnode,
  u8 flags;				/* bit 0 - high bit of first free entry offset
					   bit 5 - 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 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
					   main ea bootage pointer ea_secno
					   bit 6 - suggest binary search (unused)
					   bit 7 - 1 -> (internal) tree of anodes
						   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 n_free_nodes;			/* free 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 */
  union {
    struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
@@ -428,6 +414,16 @@ struct bplus_header
  } 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 */

/* Every file and every directory has one fnode, pointed to by the directory
+4 −4
Original line number Diff line number Diff line
@@ -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 ((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,
					   "bad number of nodes in fnode %08lx",
					    (unsigned long)ino);
					goto bail;
				}
				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,
					    "bad first_free pointer in fnode %08lx",
					    (unsigned long)ino);
@@ -187,12 +187,12 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
				goto bail;
			}
			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);
				goto bail;
			}
			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);
				goto bail;
			}