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