diff options
Diffstat (limited to 'fs/hpfs/map.c')
| -rw-r--r-- | fs/hpfs/map.c | 113 | 
1 files changed, 69 insertions, 44 deletions
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index 840d033ecee..442770edcdc 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c @@ -8,25 +8,43 @@  #include "hpfs_fn.h" -unsigned *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh) +__le32 *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh)  {  	return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0);  } -unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, +__le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,  			 struct quad_buffer_head *qbh, char *id)  {  	secno sec; -	if (hpfs_sb(s)->sb_chk) if (bmp_block * 16384 > hpfs_sb(s)->sb_fs_size) { +	__le32 *ret; +	unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; +	if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) {  		hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);  		return NULL;  	} -	sec = hpfs_sb(s)->sb_bmp_dir[bmp_block]; +	sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);  	if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) {  		hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);  		return NULL;  	} -	return hpfs_map_4sectors(s, sec, qbh, 4); +	ret = hpfs_map_4sectors(s, sec, qbh, 4); +	if (ret) hpfs_prefetch_bitmap(s, bmp_block + 1); +	return ret; +} + +void hpfs_prefetch_bitmap(struct super_block *s, unsigned bmp_block) +{ +	unsigned to_prefetch, next_prefetch; +	unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; +	if (unlikely(bmp_block >= n_bands)) +		return; +	to_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]); +	if (unlikely(bmp_block + 1 >= n_bands)) +		next_prefetch = 0; +	else +		next_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block + 1]); +	hpfs_prefetch_sectors(s, to_prefetch, 4 + 4 * (to_prefetch + 4 == next_prefetch));  }  /* @@ -46,34 +64,35 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)  	struct code_page_data *cpd;  	struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0);  	if (!cp) return NULL; -	if (cp->magic != CP_DIR_MAGIC) { -		printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", cp->magic); +	if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) { +		pr_err("Code page directory magic doesn't match (magic = %08x)\n", +			le32_to_cpu(cp->magic));  		brelse(bh);  		return NULL;  	} -	if (!cp->n_code_pages) { -		printk("HPFS: n_code_pages == 0\n"); +	if (!le32_to_cpu(cp->n_code_pages)) { +		pr_err("n_code_pages == 0\n");  		brelse(bh);  		return NULL;  	} -	cpds = cp->array[0].code_page_data; -	cpi = cp->array[0].index; +	cpds = le32_to_cpu(cp->array[0].code_page_data); +	cpi = le16_to_cpu(cp->array[0].index);  	brelse(bh);  	if (cpi >= 3) { -		printk("HPFS: Code page index out of array\n"); +		pr_err("Code page index out of array\n");  		return NULL;  	}  	if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL; -	if ((unsigned)cpd->offs[cpi] > 0x178) { -		printk("HPFS: Code page index out of sector\n"); +	if (le16_to_cpu(cpd->offs[cpi]) > 0x178) { +		pr_err("Code page index out of sector\n");  		brelse(bh);  		return NULL;  	} -	ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6; +	ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6;  	if (!(cp_table = kmalloc(256, GFP_KERNEL))) { -		printk("HPFS: out of memory for code page table\n"); +		pr_err("out of memory for code page table\n");  		brelse(bh);  		return NULL;  	} @@ -89,18 +108,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)  	return cp_table;  } -secno *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) +__le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)  {  	struct buffer_head *bh;  	int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;  	int i; -	secno *b; +	__le32 *b;  	if (!(b = kmalloc(n * 512, GFP_KERNEL))) { -		printk("HPFS: can't allocate memory for bitmap directory\n"); +		pr_err("can't allocate memory for bitmap directory\n");  		return NULL;  	}	  	for (i=0;i<n;i++) { -		secno *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1); +		__le32 *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1);  		if (!d) {  			kfree(b);  			return NULL; @@ -125,33 +144,33 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea  		if (hpfs_sb(s)->sb_chk) {  			struct extended_attribute *ea;  			struct extended_attribute *ea_end; -			if (fnode->magic != FNODE_MAGIC) { +			if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) {  				hpfs_error(s, "bad magic on fnode %08lx",  					(unsigned long)ino);  				goto bail;  			} -			if (!fnode->dirflag) { +			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 (fnode->btree.first_free != -				    8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { +				if (le16_to_cpu(fnode->btree.first_free) != +				    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);  					goto bail;  				}  			} -			if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 || -			   (signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) { +			if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 || +			   le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) {  				hpfs_error(s,  					"bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x",  					(unsigned long)ino, -					fnode->ea_offs, fnode->ea_size_s); +					le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));  				goto bail;  			}  			ea = fnode_ea(fnode); @@ -178,17 +197,21 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff  	if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL;  	if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD)))  		if (hpfs_sb(s)->sb_chk) { -			if (anode->magic != ANODE_MAGIC || anode->self != ano) { +			if (le32_to_cpu(anode->magic) != ANODE_MAGIC) {  				hpfs_error(s, "bad magic on anode %08x", ano);  				goto bail;  			} +			if (le32_to_cpu(anode->self) != ano) { +				hpfs_error(s, "self pointer invalid on anode %08x", ano); +				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 (anode->btree.first_free != -			    8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { +			if (le16_to_cpu(anode->btree.first_free) != +			    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;  			} @@ -219,26 +242,26 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,  			unsigned p, pp = 0;  			unsigned char *d = (unsigned char *)dnode;  			int b = 0; -			if (dnode->magic != DNODE_MAGIC) { +			if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) {  				hpfs_error(s, "bad magic on dnode %08x", secno);  				goto bail;  			} -			if (dnode->self != secno) -				hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, dnode->self); +			if (le32_to_cpu(dnode->self) != secno) +				hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self));  			/* Check dirents - bad dirents would cause infinite  			   loops or shooting to memory */ -			if (dnode->first_free > 2048/* || dnode->first_free < 84*/) { -				hpfs_error(s, "dnode %08x has first_free == %08x", secno, dnode->first_free); +			if (le32_to_cpu(dnode->first_free) > 2048) { +				hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free));  				goto bail;  			} -			for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) { +			for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) {  				struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); -				if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) { +				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) {  					hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);  					goto bail;  				} -				if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) { -					if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok; +				if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) { +					if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & MS_RDONLY) goto ok;  					hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);  					goto bail;  				} @@ -251,7 +274,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,  				pp = p;  			} -			if (p != dnode->first_free) { +			if (p != le32_to_cpu(dnode->first_free)) {  				hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno);  				goto bail;  			} @@ -259,7 +282,9 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,  				hpfs_error(s, "dnode %08x does not end with \\377 entry", secno);  				goto bail;  			} -			if (b == 3) printk("HPFS: warning: unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info\n", secno); +			if (b == 3) +				pr_err("unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info\n", +					secno);  		}  	return dnode;  	bail: @@ -277,7 +302,7 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino)  	if (!fnode)  		return 0; -	dno = fnode->u.external[0].disk_secno; +	dno = le32_to_cpu(fnode->u.external[0].disk_secno);  	brelse(bh);  	return dno;  }  | 
