xref: /kernel/linux/linux-6.6/fs/hpfs/map.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/fs/hpfs/map.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  mapping structures to memory with some minimal checks
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "hpfs_fn.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci__le32 *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0);
1562306a36Sopenharmony_ci}
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci__le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
1862306a36Sopenharmony_ci			 struct quad_buffer_head *qbh, char *id)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	secno sec;
2162306a36Sopenharmony_ci	__le32 *ret;
2262306a36Sopenharmony_ci	unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
2362306a36Sopenharmony_ci	if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) {
2462306a36Sopenharmony_ci		hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
2562306a36Sopenharmony_ci		return NULL;
2662306a36Sopenharmony_ci	}
2762306a36Sopenharmony_ci	sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
2862306a36Sopenharmony_ci	if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) {
2962306a36Sopenharmony_ci		hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
3062306a36Sopenharmony_ci		return NULL;
3162306a36Sopenharmony_ci	}
3262306a36Sopenharmony_ci	ret = hpfs_map_4sectors(s, sec, qbh, 4);
3362306a36Sopenharmony_ci	if (ret) hpfs_prefetch_bitmap(s, bmp_block + 1);
3462306a36Sopenharmony_ci	return ret;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_civoid hpfs_prefetch_bitmap(struct super_block *s, unsigned bmp_block)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	unsigned to_prefetch, next_prefetch;
4062306a36Sopenharmony_ci	unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
4162306a36Sopenharmony_ci	if (unlikely(bmp_block >= n_bands))
4262306a36Sopenharmony_ci		return;
4362306a36Sopenharmony_ci	to_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
4462306a36Sopenharmony_ci	if (unlikely(bmp_block + 1 >= n_bands))
4562306a36Sopenharmony_ci		next_prefetch = 0;
4662306a36Sopenharmony_ci	else
4762306a36Sopenharmony_ci		next_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block + 1]);
4862306a36Sopenharmony_ci	hpfs_prefetch_sectors(s, to_prefetch, 4 + 4 * (to_prefetch + 4 == next_prefetch));
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * Load first code page into kernel memory, return pointer to 256-byte array,
5362306a36Sopenharmony_ci * first 128 bytes are uppercasing table for chars 128-255, next 128 bytes are
5462306a36Sopenharmony_ci * lowercasing table
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciunsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	struct buffer_head *bh;
6062306a36Sopenharmony_ci	secno cpds;
6162306a36Sopenharmony_ci	unsigned cpi;
6262306a36Sopenharmony_ci	unsigned char *ptr;
6362306a36Sopenharmony_ci	unsigned char *cp_table;
6462306a36Sopenharmony_ci	int i;
6562306a36Sopenharmony_ci	struct code_page_data *cpd;
6662306a36Sopenharmony_ci	struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0);
6762306a36Sopenharmony_ci	if (!cp) return NULL;
6862306a36Sopenharmony_ci	if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) {
6962306a36Sopenharmony_ci		pr_err("Code page directory magic doesn't match (magic = %08x)\n",
7062306a36Sopenharmony_ci			le32_to_cpu(cp->magic));
7162306a36Sopenharmony_ci		brelse(bh);
7262306a36Sopenharmony_ci		return NULL;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci	if (!le32_to_cpu(cp->n_code_pages)) {
7562306a36Sopenharmony_ci		pr_err("n_code_pages == 0\n");
7662306a36Sopenharmony_ci		brelse(bh);
7762306a36Sopenharmony_ci		return NULL;
7862306a36Sopenharmony_ci	}
7962306a36Sopenharmony_ci	cpds = le32_to_cpu(cp->array[0].code_page_data);
8062306a36Sopenharmony_ci	cpi = le16_to_cpu(cp->array[0].index);
8162306a36Sopenharmony_ci	brelse(bh);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	if (cpi >= 3) {
8462306a36Sopenharmony_ci		pr_err("Code page index out of array\n");
8562306a36Sopenharmony_ci		return NULL;
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL;
8962306a36Sopenharmony_ci	if (le16_to_cpu(cpd->offs[cpi]) > 0x178) {
9062306a36Sopenharmony_ci		pr_err("Code page index out of sector\n");
9162306a36Sopenharmony_ci		brelse(bh);
9262306a36Sopenharmony_ci		return NULL;
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci	ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6;
9562306a36Sopenharmony_ci	if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
9662306a36Sopenharmony_ci		pr_err("out of memory for code page table\n");
9762306a36Sopenharmony_ci		brelse(bh);
9862306a36Sopenharmony_ci		return NULL;
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci	memcpy(cp_table, ptr, 128);
10162306a36Sopenharmony_ci	brelse(bh);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* Try to build lowercasing table from uppercasing one */
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	for (i=128; i<256; i++) cp_table[i]=i;
10662306a36Sopenharmony_ci	for (i=128; i<256; i++) if (cp_table[i-128]!=i && cp_table[i-128]>=128)
10762306a36Sopenharmony_ci		cp_table[cp_table[i-128]] = i;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	return cp_table;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci__le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	struct buffer_head *bh;
11562306a36Sopenharmony_ci	int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;
11662306a36Sopenharmony_ci	int i;
11762306a36Sopenharmony_ci	__le32 *b;
11862306a36Sopenharmony_ci	if (!(b = kmalloc_array(n, 512, GFP_KERNEL))) {
11962306a36Sopenharmony_ci		pr_err("can't allocate memory for bitmap directory\n");
12062306a36Sopenharmony_ci		return NULL;
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci	for (i=0;i<n;i++) {
12362306a36Sopenharmony_ci		__le32 *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1);
12462306a36Sopenharmony_ci		if (!d) {
12562306a36Sopenharmony_ci			kfree(b);
12662306a36Sopenharmony_ci			return NULL;
12762306a36Sopenharmony_ci		}
12862306a36Sopenharmony_ci		memcpy((char *)b + 512 * i, d, 512);
12962306a36Sopenharmony_ci		brelse(bh);
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci	return b;
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_civoid hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct quad_buffer_head qbh;
13762306a36Sopenharmony_ci	__le32 *directory;
13862306a36Sopenharmony_ci	u32 n_hotfixes, n_used_hotfixes;
13962306a36Sopenharmony_ci	unsigned i;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	n_hotfixes = le32_to_cpu(spareblock->n_spares);
14262306a36Sopenharmony_ci	n_used_hotfixes = le32_to_cpu(spareblock->n_spares_used);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (n_hotfixes > 256 || n_used_hotfixes > n_hotfixes) {
14562306a36Sopenharmony_ci		hpfs_error(s, "invalid number of hotfixes: %u, used: %u", n_hotfixes, n_used_hotfixes);
14662306a36Sopenharmony_ci		return;
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci	if (!(directory = hpfs_map_4sectors(s, le32_to_cpu(spareblock->hotfix_map), &qbh, 0))) {
14962306a36Sopenharmony_ci		hpfs_error(s, "can't load hotfix map");
15062306a36Sopenharmony_ci		return;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci	for (i = 0; i < n_used_hotfixes; i++) {
15362306a36Sopenharmony_ci		hpfs_sb(s)->hotfix_from[i] = le32_to_cpu(directory[i]);
15462306a36Sopenharmony_ci		hpfs_sb(s)->hotfix_to[i] = le32_to_cpu(directory[n_hotfixes + i]);
15562306a36Sopenharmony_ci	}
15662306a36Sopenharmony_ci	hpfs_sb(s)->n_hotfixes = n_used_hotfixes;
15762306a36Sopenharmony_ci	hpfs_brelse4(&qbh);
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/*
16162306a36Sopenharmony_ci * Load fnode to memory
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistruct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_head **bhp)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct fnode *fnode;
16762306a36Sopenharmony_ci	if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ino, 1, "fnode")) {
16862306a36Sopenharmony_ci		return NULL;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	if ((fnode = hpfs_map_sector(s, ino, bhp, FNODE_RD_AHEAD))) {
17162306a36Sopenharmony_ci		if (hpfs_sb(s)->sb_chk) {
17262306a36Sopenharmony_ci			struct extended_attribute *ea;
17362306a36Sopenharmony_ci			struct extended_attribute *ea_end;
17462306a36Sopenharmony_ci			if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) {
17562306a36Sopenharmony_ci				hpfs_error(s, "bad magic on fnode %08lx",
17662306a36Sopenharmony_ci					(unsigned long)ino);
17762306a36Sopenharmony_ci				goto bail;
17862306a36Sopenharmony_ci			}
17962306a36Sopenharmony_ci			if (!fnode_is_dir(fnode)) {
18062306a36Sopenharmony_ci				if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes !=
18162306a36Sopenharmony_ci				    (bp_internal(&fnode->btree) ? 12 : 8)) {
18262306a36Sopenharmony_ci					hpfs_error(s,
18362306a36Sopenharmony_ci					   "bad number of nodes in fnode %08lx",
18462306a36Sopenharmony_ci					    (unsigned long)ino);
18562306a36Sopenharmony_ci					goto bail;
18662306a36Sopenharmony_ci				}
18762306a36Sopenharmony_ci				if (le16_to_cpu(fnode->btree.first_free) !=
18862306a36Sopenharmony_ci				    8 + fnode->btree.n_used_nodes * (bp_internal(&fnode->btree) ? 8 : 12)) {
18962306a36Sopenharmony_ci					hpfs_error(s,
19062306a36Sopenharmony_ci					    "bad first_free pointer in fnode %08lx",
19162306a36Sopenharmony_ci					    (unsigned long)ino);
19262306a36Sopenharmony_ci					goto bail;
19362306a36Sopenharmony_ci				}
19462306a36Sopenharmony_ci			}
19562306a36Sopenharmony_ci			if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 ||
19662306a36Sopenharmony_ci			   le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) {
19762306a36Sopenharmony_ci				hpfs_error(s,
19862306a36Sopenharmony_ci					"bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x",
19962306a36Sopenharmony_ci					(unsigned long)ino,
20062306a36Sopenharmony_ci					le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
20162306a36Sopenharmony_ci				goto bail;
20262306a36Sopenharmony_ci			}
20362306a36Sopenharmony_ci			ea = fnode_ea(fnode);
20462306a36Sopenharmony_ci			ea_end = fnode_end_ea(fnode);
20562306a36Sopenharmony_ci			while (ea != ea_end) {
20662306a36Sopenharmony_ci				if (ea > ea_end) {
20762306a36Sopenharmony_ci					hpfs_error(s, "bad EA in fnode %08lx",
20862306a36Sopenharmony_ci						(unsigned long)ino);
20962306a36Sopenharmony_ci					goto bail;
21062306a36Sopenharmony_ci				}
21162306a36Sopenharmony_ci				ea = next_ea(ea);
21262306a36Sopenharmony_ci			}
21362306a36Sopenharmony_ci		}
21462306a36Sopenharmony_ci	}
21562306a36Sopenharmony_ci	return fnode;
21662306a36Sopenharmony_ci	bail:
21762306a36Sopenharmony_ci	brelse(*bhp);
21862306a36Sopenharmony_ci	return NULL;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistruct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buffer_head **bhp)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	struct anode *anode;
22462306a36Sopenharmony_ci	if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL;
22562306a36Sopenharmony_ci	if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD)))
22662306a36Sopenharmony_ci		if (hpfs_sb(s)->sb_chk) {
22762306a36Sopenharmony_ci			if (le32_to_cpu(anode->magic) != ANODE_MAGIC) {
22862306a36Sopenharmony_ci				hpfs_error(s, "bad magic on anode %08x", ano);
22962306a36Sopenharmony_ci				goto bail;
23062306a36Sopenharmony_ci			}
23162306a36Sopenharmony_ci			if (le32_to_cpu(anode->self) != ano) {
23262306a36Sopenharmony_ci				hpfs_error(s, "self pointer invalid on anode %08x", ano);
23362306a36Sopenharmony_ci				goto bail;
23462306a36Sopenharmony_ci			}
23562306a36Sopenharmony_ci			if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
23662306a36Sopenharmony_ci			    (bp_internal(&anode->btree) ? 60 : 40)) {
23762306a36Sopenharmony_ci				hpfs_error(s, "bad number of nodes in anode %08x", ano);
23862306a36Sopenharmony_ci				goto bail;
23962306a36Sopenharmony_ci			}
24062306a36Sopenharmony_ci			if (le16_to_cpu(anode->btree.first_free) !=
24162306a36Sopenharmony_ci			    8 + anode->btree.n_used_nodes * (bp_internal(&anode->btree) ? 8 : 12)) {
24262306a36Sopenharmony_ci				hpfs_error(s, "bad first_free pointer in anode %08x", ano);
24362306a36Sopenharmony_ci				goto bail;
24462306a36Sopenharmony_ci			}
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci	return anode;
24762306a36Sopenharmony_ci	bail:
24862306a36Sopenharmony_ci	brelse(*bhp);
24962306a36Sopenharmony_ci	return NULL;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/*
25362306a36Sopenharmony_ci * Load dnode to memory and do some checks
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistruct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
25762306a36Sopenharmony_ci			     struct quad_buffer_head *qbh)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	struct dnode *dnode;
26062306a36Sopenharmony_ci	if (hpfs_sb(s)->sb_chk) {
26162306a36Sopenharmony_ci		if (hpfs_chk_sectors(s, secno, 4, "dnode")) return NULL;
26262306a36Sopenharmony_ci		if (secno & 3) {
26362306a36Sopenharmony_ci			hpfs_error(s, "dnode %08x not byte-aligned", secno);
26462306a36Sopenharmony_ci			return NULL;
26562306a36Sopenharmony_ci		}
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci	if ((dnode = hpfs_map_4sectors(s, secno, qbh, DNODE_RD_AHEAD)))
26862306a36Sopenharmony_ci		if (hpfs_sb(s)->sb_chk) {
26962306a36Sopenharmony_ci			unsigned p, pp = 0;
27062306a36Sopenharmony_ci			unsigned char *d = (unsigned char *)dnode;
27162306a36Sopenharmony_ci			int b = 0;
27262306a36Sopenharmony_ci			if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) {
27362306a36Sopenharmony_ci				hpfs_error(s, "bad magic on dnode %08x", secno);
27462306a36Sopenharmony_ci				goto bail;
27562306a36Sopenharmony_ci			}
27662306a36Sopenharmony_ci			if (le32_to_cpu(dnode->self) != secno)
27762306a36Sopenharmony_ci				hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self));
27862306a36Sopenharmony_ci			/* Check dirents - bad dirents would cause infinite
27962306a36Sopenharmony_ci			   loops or shooting to memory */
28062306a36Sopenharmony_ci			if (le32_to_cpu(dnode->first_free) > 2048) {
28162306a36Sopenharmony_ci				hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free));
28262306a36Sopenharmony_ci				goto bail;
28362306a36Sopenharmony_ci			}
28462306a36Sopenharmony_ci			for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) {
28562306a36Sopenharmony_ci				struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p);
28662306a36Sopenharmony_ci				if (le16_to_cpu(de->length) > 292 || (le16_to_cpu(de->length) < 32) || (le16_to_cpu(de->length) & 3) || p + le16_to_cpu(de->length) > 2048) {
28762306a36Sopenharmony_ci					hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
28862306a36Sopenharmony_ci					goto bail;
28962306a36Sopenharmony_ci				}
29062306a36Sopenharmony_ci				if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) {
29162306a36Sopenharmony_ci					if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & SB_RDONLY) goto ok;
29262306a36Sopenharmony_ci					hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
29362306a36Sopenharmony_ci					goto bail;
29462306a36Sopenharmony_ci				}
29562306a36Sopenharmony_ci				ok:
29662306a36Sopenharmony_ci				if (hpfs_sb(s)->sb_chk >= 2) b |= 1 << de->down;
29762306a36Sopenharmony_ci				if (de->down) if (de_down_pointer(de) < 0x10) {
29862306a36Sopenharmony_ci					hpfs_error(s, "bad down pointer in dnode %08x, dirent %03x, last %03x", secno, p, pp);
29962306a36Sopenharmony_ci					goto bail;
30062306a36Sopenharmony_ci				}
30162306a36Sopenharmony_ci				pp = p;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci			}
30462306a36Sopenharmony_ci			if (p != le32_to_cpu(dnode->first_free)) {
30562306a36Sopenharmony_ci				hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno);
30662306a36Sopenharmony_ci				goto bail;
30762306a36Sopenharmony_ci			}
30862306a36Sopenharmony_ci			if (d[pp + 30] != 1 || d[pp + 31] != 255) {
30962306a36Sopenharmony_ci				hpfs_error(s, "dnode %08x does not end with \\377 entry", secno);
31062306a36Sopenharmony_ci				goto bail;
31162306a36Sopenharmony_ci			}
31262306a36Sopenharmony_ci			if (b == 3)
31362306a36Sopenharmony_ci				pr_err("unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info\n",
31462306a36Sopenharmony_ci					secno);
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci	return dnode;
31762306a36Sopenharmony_ci	bail:
31862306a36Sopenharmony_ci	hpfs_brelse4(qbh);
31962306a36Sopenharmony_ci	return NULL;
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cidnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	struct buffer_head *bh;
32562306a36Sopenharmony_ci	struct fnode *fnode;
32662306a36Sopenharmony_ci	dnode_secno dno;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	fnode = hpfs_map_fnode(s, ino, &bh);
32962306a36Sopenharmony_ci	if (!fnode)
33062306a36Sopenharmony_ci		return 0;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	dno = le32_to_cpu(fnode->u.external[0].disk_secno);
33362306a36Sopenharmony_ci	brelse(bh);
33462306a36Sopenharmony_ci	return dno;
33562306a36Sopenharmony_ci}
336