diff options
Diffstat (limited to 'fs/hpfs')
| -rw-r--r-- | fs/hpfs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/hpfs/alloc.c | 184 | ||||
| -rw-r--r-- | fs/hpfs/anode.c | 179 | ||||
| -rw-r--r-- | fs/hpfs/buffer.c | 160 | ||||
| -rw-r--r-- | fs/hpfs/dentry.c | 29 | ||||
| -rw-r--r-- | fs/hpfs/dir.c | 124 | ||||
| -rw-r--r-- | fs/hpfs/dnode.c | 220 | ||||
| -rw-r--r-- | fs/hpfs/ea.c | 190 | ||||
| -rw-r--r-- | fs/hpfs/file.c | 142 | ||||
| -rw-r--r-- | fs/hpfs/hpfs.h | 504 | ||||
| -rw-r--r-- | fs/hpfs/hpfs_fn.h | 129 | ||||
| -rw-r--r-- | fs/hpfs/inode.c | 99 | ||||
| -rw-r--r-- | fs/hpfs/map.c | 113 | ||||
| -rw-r--r-- | fs/hpfs/name.c | 44 | ||||
| -rw-r--r-- | fs/hpfs/namei.c | 189 | ||||
| -rw-r--r-- | fs/hpfs/super.c | 297 | 
16 files changed, 1393 insertions, 1211 deletions
diff --git a/fs/hpfs/Kconfig b/fs/hpfs/Kconfig index 63b6f563231..56bd15c5bf6 100644 --- a/fs/hpfs/Kconfig +++ b/fs/hpfs/Kconfig @@ -1,7 +1,6 @@  config HPFS_FS  	tristate "OS/2 HPFS file system support"  	depends on BLOCK -	depends on BKL # nontrivial to fix  	help  	  OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS  	  is the file system used for organizing files on OS/2 hard disk diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index 5503e2c2891..f005046e159 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c @@ -8,7 +8,57 @@  #include "hpfs_fn.h" -static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec); +static void hpfs_claim_alloc(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free != (unsigned)-1) { +		if (unlikely(!sbi->sb_n_free)) { +			hpfs_error(s, "free count underflow, allocating sector %08x", sec); +			sbi->sb_n_free = -1; +			return; +		} +		sbi->sb_n_free--; +	} +} + +static void hpfs_claim_free(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free != (unsigned)-1) { +		if (unlikely(sbi->sb_n_free >= sbi->sb_fs_size)) { +			hpfs_error(s, "free count overflow, freeing sector %08x", sec); +			sbi->sb_n_free = -1; +			return; +		} +		sbi->sb_n_free++; +	} +} + +static void hpfs_claim_dirband_alloc(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free_dnodes != (unsigned)-1) { +		if (unlikely(!sbi->sb_n_free_dnodes)) { +			hpfs_error(s, "dirband free count underflow, allocating sector %08x", sec); +			sbi->sb_n_free_dnodes = -1; +			return; +		} +		sbi->sb_n_free_dnodes--; +	} +} + +static void hpfs_claim_dirband_free(struct super_block *s, secno sec) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free_dnodes != (unsigned)-1) { +		if (unlikely(sbi->sb_n_free_dnodes >= sbi->sb_dirband_size / 4)) { +			hpfs_error(s, "dirband free count overflow, freeing sector %08x", sec); +			sbi->sb_n_free_dnodes = -1; +			return; +		} +		sbi->sb_n_free_dnodes++; +	} +}  /*   * Check if a sector is allocated in bitmap @@ -18,9 +68,9 @@ static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec);  static int chk_if_allocated(struct super_block *s, secno sec, char *msg)  {  	struct quad_buffer_head qbh; -	unsigned *bmp; +	__le32 *bmp;  	if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail; -	if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f)) & 1) { +	if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) {  		hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec);  		goto fail1;  	} @@ -28,7 +78,7 @@ static int chk_if_allocated(struct super_block *s, secno sec, char *msg)  	if (sec >= hpfs_sb(s)->sb_dirband_start && sec < hpfs_sb(s)->sb_dirband_start + hpfs_sb(s)->sb_dirband_size) {  		unsigned ssec = (sec - hpfs_sb(s)->sb_dirband_start) / 4;  		if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto fail; -		if ((bmp[ssec >> 5] >> (ssec & 0x1f)) & 1) { +		if ((le32_to_cpu(bmp[ssec >> 5]) >> (ssec & 0x1f)) & 1) {  			hpfs_error(s, "sector '%s' - %08x not allocated in directory bitmap", msg, sec);  			goto fail1;  		} @@ -64,7 +114,7 @@ int hpfs_chk_sectors(struct super_block *s, secno start, int len, char *msg)  static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigned forward)  {  	struct quad_buffer_head qbh; -	unsigned *bmp; +	__le32 *bmp;  	unsigned bs = near & ~0x3fff;  	unsigned nr = (near & 0x3fff) & ~(n - 1);  	/*unsigned mnr;*/ @@ -75,7 +125,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne  		hpfs_error(s, "Bad allocation size: %d", n);  		return 0;  	} -	lock_super(s);  	if (bs != ~0x3fff) {  		if (!(bmp = hpfs_map_bitmap(s, near >> 14, &qbh, "aib"))) goto uls;  	} else { @@ -85,10 +134,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne  		ret = bs + nr;  		goto rt;  	} -	/*if (!tstbits(bmp, nr + n, n + forward)) { -		ret = bs + nr + n; -		goto rt; -	}*/  	q = nr + n; b = 0;  	while ((a = tstbits(bmp, q, n + forward)) != 0) {  		q += a; @@ -105,14 +150,14 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne  		goto rt;  	}  	nr >>= 5; -	/*for (i = nr + 1; i != nr; i++, i &= 0x1ff) {*/ +	/*for (i = nr + 1; i != nr; i++, i &= 0x1ff) */  	i = nr;  	do { -		if (!bmp[i]) goto cont; -		if (n + forward >= 0x3f && bmp[i] != -1) goto cont; +		if (!le32_to_cpu(bmp[i])) goto cont; +		if (n + forward >= 0x3f && le32_to_cpu(bmp[i]) != 0xffffffff) goto cont;  		q = i<<5;  		if (i > 0) { -			unsigned k = bmp[i-1]; +			unsigned k = le32_to_cpu(bmp[i-1]);  			while (k & 0x80000000) {  				q--; k <<= 1;  			} @@ -132,18 +177,17 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne  	} while (i != nr);  	rt:  	if (ret) { -		if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (bmp[(ret & 0x3fff) >> 5] | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) { +		if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (le32_to_cpu(bmp[(ret & 0x3fff) >> 5]) | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) {  			hpfs_error(s, "Allocation doesn't work! Wanted %d, allocated at %08x", n, ret);  			ret = 0;  			goto b;  		} -		bmp[(ret & 0x3fff) >> 5] &= ~(((1 << n) - 1) << (ret & 0x1f)); +		bmp[(ret & 0x3fff) >> 5] &= cpu_to_le32(~(((1 << n) - 1) << (ret & 0x1f)));  		hpfs_mark_4buffers_dirty(&qbh);  	}  	b:  	hpfs_brelse4(&qbh);  	uls: -	unlock_super(s);  	return ret;  } @@ -155,7 +199,7 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne   *				sectors   */ -secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward, int lock) +secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward)  {  	secno sec;  	int i; @@ -167,7 +211,6 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa  		forward = -forward;  		f_p = 1;  	} -	if (lock) hpfs_lock_creation(s);  	n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14;  	if (near && near < sbi->sb_fs_size) {  		if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret; @@ -212,20 +255,25 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa  	}  	sec = 0;  	ret: +	if (sec) { +		i = 0; +		do +			hpfs_claim_alloc(s, sec + i); +		while (unlikely(++i < n)); +	}  	if (sec && f_p) {  		for (i = 0; i < forward; i++) { -			if (!hpfs_alloc_if_possible_nolock(s, sec + i + 1)) { +			if (!hpfs_alloc_if_possible(s, sec + n + i)) {  				hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i);  				sec = 0;  				break;  			}  		}  	} -	if (lock) hpfs_unlock_creation(s);  	return sec;  } -static secno alloc_in_dirband(struct super_block *s, secno near, int lock) +static secno alloc_in_dirband(struct super_block *s, secno near)  {  	unsigned nr = near;  	secno sec; @@ -236,76 +284,61 @@ static secno alloc_in_dirband(struct super_block *s, secno near, int lock)  		nr = sbi->sb_dirband_start + sbi->sb_dirband_size - 4;  	nr -= sbi->sb_dirband_start;  	nr >>= 2; -	if (lock) hpfs_lock_creation(s);  	sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0); -	if (lock) hpfs_unlock_creation(s);  	if (!sec) return 0; +	hpfs_claim_dirband_alloc(s, sec);  	return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start;  }  /* Alloc sector if it's free */ -static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec) +int hpfs_alloc_if_possible(struct super_block *s, secno sec)  {  	struct quad_buffer_head qbh; -	unsigned *bmp; -	lock_super(s); +	__le32 *bmp;  	if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end; -	if (bmp[(sec & 0x3fff) >> 5] & (1 << (sec & 0x1f))) { -		bmp[(sec & 0x3fff) >> 5] &= ~(1 << (sec & 0x1f)); +	if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) { +		bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh); -		unlock_super(s); +		hpfs_claim_alloc(s, sec);  		return 1;  	}  	hpfs_brelse4(&qbh);  	end: -	unlock_super(s);  	return 0;  } -int hpfs_alloc_if_possible(struct super_block *s, secno sec) -{ -	int r; -	hpfs_lock_creation(s); -	r = hpfs_alloc_if_possible_nolock(s, sec); -	hpfs_unlock_creation(s); -	return r; -} -  /* Free sectors in bitmaps */  void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)  {  	struct quad_buffer_head qbh; -	unsigned *bmp; +	__le32 *bmp;  	struct hpfs_sb_info *sbi = hpfs_sb(s); -	/*printk("2 - ");*/ +	/*pr_info("2 - ");*/  	if (!n) return;  	if (sec < 0x12) {  		hpfs_error(s, "Trying to free reserved sector %08x", sec);  		return;  	} -	lock_super(s);  	sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n;  	if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff;  	new_map:  	if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) { -		unlock_super(s);  		return;  	}	  	new_tst: -	if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f) & 1)) { +	if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f) & 1)) {  		hpfs_error(s, "sector %08x not allocated", sec);  		hpfs_brelse4(&qbh); -		unlock_super(s);  		return;  	} -	bmp[(sec & 0x3fff) >> 5] |= 1 << (sec & 0x1f); +	bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f)); +	hpfs_claim_free(s, sec);  	if (!--n) {  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh); -		unlock_super(s);  		return;  	}	  	if (!(++sec & 0x3fff)) { @@ -327,13 +360,13 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)  	int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14;  	int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff;  	int i, j; -	unsigned *bmp; +	__le32 *bmp;  	struct quad_buffer_head qbh;  	if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {  		for (j = 0; j < 512; j++) {  			unsigned k; -			if (!bmp[j]) continue; -			for (k = bmp[j]; k; k >>= 1) if (k & 1) if (!--n) { +			if (!le32_to_cpu(bmp[j])) continue; +			for (k = le32_to_cpu(bmp[j]); k; k >>= 1) if (k & 1) if (!--n) {  				hpfs_brelse4(&qbh);  				return 0;  			} @@ -352,10 +385,10 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)  	chk_bmp:  	if (bmp) {  		for (j = 0; j < 512; j++) { -			unsigned k; -			if (!bmp[j]) continue; +			u32 k; +			if (!le32_to_cpu(bmp[j])) continue;  			for (k = 0xf; k; k <<= 4) -				if ((bmp[j] & k) == k) { +				if ((le32_to_cpu(bmp[j]) & k) == k) {  					if (!--n) {  						hpfs_brelse4(&qbh);  						return 0; @@ -379,44 +412,41 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno)  		hpfs_free_sectors(s, dno, 4);  	} else {  		struct quad_buffer_head qbh; -		unsigned *bmp; +		__le32 *bmp;  		unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4; -		lock_super(s);  		if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { -			unlock_super(s);  			return;  		} -		bmp[ssec >> 5] |= 1 << (ssec & 0x1f); +		bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f));  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh); -		unlock_super(s); +		hpfs_claim_dirband_free(s, dno);  	}  }  struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near, -			 dnode_secno *dno, struct quad_buffer_head *qbh, -			 int lock) +			 dnode_secno *dno, struct quad_buffer_head *qbh)  {  	struct dnode *d; -	if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) { -		if (!(*dno = alloc_in_dirband(s, near, lock))) -			if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) return NULL; +	if (hpfs_get_free_dnodes(s) > FREE_DNODES_ADD) { +		if (!(*dno = alloc_in_dirband(s, near))) +			if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL;  	} else { -		if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) -			if (!(*dno = alloc_in_dirband(s, near, lock))) return NULL; +		if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) +			if (!(*dno = alloc_in_dirband(s, near))) return NULL;  	}  	if (!(d = hpfs_get_4sectors(s, *dno, qbh))) {  		hpfs_free_dnode(s, *dno);  		return NULL;  	}  	memset(d, 0, 2048); -	d->magic = DNODE_MAGIC; -	d->first_free = 52; +	d->magic = cpu_to_le32(DNODE_MAGIC); +	d->first_free = cpu_to_le32(52);  	d->dirent[0] = 32;  	d->dirent[2] = 8;  	d->dirent[30] = 1;  	d->dirent[31] = 255; -	d->self = *dno; +	d->self = cpu_to_le32(*dno);  	return d;  } @@ -424,16 +454,16 @@ struct fnode *hpfs_alloc_fnode(struct super_block *s, secno near, fnode_secno *f  			  struct buffer_head **bh)  {  	struct fnode *f; -	if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD, 1))) return NULL; +	if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD))) return NULL;  	if (!(f = hpfs_get_sector(s, *fno, bh))) {  		hpfs_free_sectors(s, *fno, 1);  		return NULL;  	}	  	memset(f, 0, 512); -	f->magic = FNODE_MAGIC; -	f->ea_offs = 0xc4; +	f->magic = cpu_to_le32(FNODE_MAGIC); +	f->ea_offs = cpu_to_le16(0xc4);  	f->btree.n_free_nodes = 8; -	f->btree.first_free = 8; +	f->btree.first_free = cpu_to_le16(8);  	return f;  } @@ -441,16 +471,16 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a  			  struct buffer_head **bh)  {  	struct anode *a; -	if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD, 1))) return NULL; +	if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD))) return NULL;  	if (!(a = hpfs_get_sector(s, *ano, bh))) {  		hpfs_free_sectors(s, *ano, 1);  		return NULL;  	}  	memset(a, 0, 512); -	a->magic = ANODE_MAGIC; -	a->self = *ano; +	a->magic = cpu_to_le32(ANODE_MAGIC); +	a->self = cpu_to_le32(*ano);  	a->btree.n_free_nodes = 40;  	a->btree.n_used_nodes = 0; -	a->btree.first_free = 8; +	a->btree.first_free = cpu_to_le16(8);  	return a;  } diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c index 6a2f04bf3df..2d5b254ad9e 100644 --- a/fs/hpfs/anode.c +++ b/fs/hpfs/anode.c @@ -20,10 +20,10 @@ 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 (btree->u.internal[i].file_secno > sec) { -				a = btree->u.internal[i].down; +			if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) { +				a = le32_to_cpu(btree->u.internal[i].down);  				brelse(bh);  				if (!(anode = hpfs_map_anode(s, a, &bh))) return -1;  				btree = &anode->btree; @@ -34,18 +34,18 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,  		return -1;  	}  	for (i = 0; i < btree->n_used_nodes; i++) -		if (btree->u.external[i].file_secno <= sec && -		    btree->u.external[i].file_secno + btree->u.external[i].length > sec) { -			a = btree->u.external[i].disk_secno + sec - btree->u.external[i].file_secno; +		if (le32_to_cpu(btree->u.external[i].file_secno) <= sec && +		    le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > sec) { +			a = le32_to_cpu(btree->u.external[i].disk_secno) + sec - le32_to_cpu(btree->u.external[i].file_secno);  			if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, a, 1, "data")) {  				brelse(bh);  				return -1;  			}  			if (inode) {  				struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); -				hpfs_inode->i_file_sec = btree->u.external[i].file_secno; -				hpfs_inode->i_disk_sec = btree->u.external[i].disk_secno; -				hpfs_inode->i_n_secs = btree->u.external[i].length; +				hpfs_inode->i_file_sec = le32_to_cpu(btree->u.external[i].file_secno); +				hpfs_inode->i_disk_sec = le32_to_cpu(btree->u.external[i].disk_secno); +				hpfs_inode->i_n_secs = le32_to_cpu(btree->u.external[i].length);  			}  			brelse(bh);  			return a; @@ -82,9 +82,9 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi  		brelse(bh);  		return -1;  	} -	if (btree->internal) { -		a = btree->u.internal[n].down; -		btree->u.internal[n].file_secno = -1; +	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);  		brelse(bh);  		if (hpfs_sb(s)->sb_chk) @@ -94,15 +94,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi  		goto go_down;  	}  	if (n >= 0) { -		if (btree->u.external[n].file_secno + btree->u.external[n].length != fsecno) { +		if (le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length) != fsecno) {  			hpfs_error(s, "allocated size %08x, trying to add sector %08x, %cnode %08x", -				btree->u.external[n].file_secno + btree->u.external[n].length, fsecno, +				le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length), fsecno,  				fnod?'f':'a', node);  			brelse(bh);  			return -1;  		} -		if (hpfs_alloc_if_possible(s, se = btree->u.external[n].disk_secno + btree->u.external[n].length)) { -			btree->u.external[n].length++; +		if (hpfs_alloc_if_possible(s, se = le32_to_cpu(btree->u.external[n].disk_secno) + le32_to_cpu(btree->u.external[n].length))) { +			le32_add_cpu(&btree->u.external[n].length, 1);  			mark_buffer_dirty(bh);  			brelse(bh);  			return se; @@ -115,31 +115,31 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi  		}  		se = !fnod ? node : (node + 16384) & ~16383;  	}	 -	if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) { +	if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M))) {  		brelse(bh);  		return -1;  	} -	fs = n < 0 ? 0 : btree->u.external[n].file_secno + btree->u.external[n].length; +	fs = n < 0 ? 0 : le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length);  	if (!btree->n_free_nodes) { -		up = a != node ? anode->up : -1; +		up = a != node ? le32_to_cpu(anode->up) : -1;  		if (!(anode = hpfs_alloc_anode(s, a, &na, &bh1))) {  			brelse(bh);  			hpfs_free_sectors(s, se, 1);  			return -1;  		}  		if (a == node && fnod) { -			anode->up = node; -			anode->btree.fnode_parent = 1; +			anode->up = cpu_to_le32(node); +			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 = (char *)&(btree->u.internal[1]) - (char *)btree; -			btree->u.internal[0].file_secno = -1; -			btree->u.internal[0].down = na; +			btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree); +			btree->u.internal[0].file_secno = cpu_to_le32(-1); +			btree->u.internal[0].down = cpu_to_le32(na);  			mark_buffer_dirty(bh);  		} else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) {  			brelse(bh); @@ -153,15 +153,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi  		btree = &anode->btree;  	}  	btree->n_free_nodes--; n = btree->n_used_nodes++; -	btree->first_free += 12; -	btree->u.external[n].disk_secno = se; -	btree->u.external[n].file_secno = fs; -	btree->u.external[n].length = 1; +	le16_add_cpu(&btree->first_free, 12); +	btree->u.external[n].disk_secno = cpu_to_le32(se); +	btree->u.external[n].file_secno = cpu_to_le32(fs); +	btree->u.external[n].length = cpu_to_le32(1);  	mark_buffer_dirty(bh);  	brelse(bh);  	if ((a == node && fnod) || na == -1) return se;  	c2 = 0; -	while (up != -1) { +	while (up != (anode_secno)-1) {  		struct anode *new_anode;  		if (hpfs_sb(s)->sb_chk)  			if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1; @@ -174,48 +174,52 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi  		}  		if (btree->n_free_nodes) {  			btree->n_free_nodes--; n = btree->n_used_nodes++; -			btree->first_free += 8; -			btree->u.internal[n].file_secno = -1; -			btree->u.internal[n].down = na; -			btree->u.internal[n-1].file_secno = fs; +			le16_add_cpu(&btree->first_free, 8); +			btree->u.internal[n].file_secno = cpu_to_le32(-1); +			btree->u.internal[n].down = cpu_to_le32(na); +			btree->u.internal[n-1].file_secno = cpu_to_le32(fs);  			mark_buffer_dirty(bh);  			brelse(bh);  			brelse(bh2);  			hpfs_free_sectors(s, ra, 1);  			if ((anode = hpfs_map_anode(s, na, &bh))) { -				anode->up = up; -				anode->btree.fnode_parent = up == node && fnod; +				anode->up = cpu_to_le32(up); +				if (up == node && fnod) +					anode->btree.flags |= BP_fnode_parent; +				else +					anode->btree.flags &= ~BP_fnode_parent;  				mark_buffer_dirty(bh);  				brelse(bh);  			}  			return se;  		} -		up = up != node ? anode->up : -1; -		btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1; +		up = up != node ? le32_to_cpu(anode->up) : -1; +		btree->u.internal[btree->n_used_nodes - 1].file_secno = cpu_to_le32(/*fs*/-1);  		mark_buffer_dirty(bh);  		brelse(bh);  		a = na;  		if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) {  			anode = new_anode; -			/*anode->up = up != -1 ? up : ra;*/ -			anode->btree.internal = 1; +			/*anode->up = cpu_to_le32(up != -1 ? up : ra);*/ +			anode->btree.flags |= BP_internal;  			anode->btree.n_used_nodes = 1;  			anode->btree.n_free_nodes = 59; -			anode->btree.first_free = 16; -			anode->btree.u.internal[0].down = a; -			anode->btree.u.internal[0].file_secno = -1; +			anode->btree.first_free = cpu_to_le16(16); +			anode->btree.u.internal[0].down = cpu_to_le32(a); +			anode->btree.u.internal[0].file_secno = cpu_to_le32(-1);  			mark_buffer_dirty(bh);  			brelse(bh);  			if ((anode = hpfs_map_anode(s, a, &bh))) { -				anode->up = na; +				anode->up = cpu_to_le32(na);  				mark_buffer_dirty(bh);  				brelse(bh);  			}  		} else na = a;  	}  	if ((anode = hpfs_map_anode(s, na, &bh))) { -		anode->up = node; -		if (fnod) anode->btree.fnode_parent = 1; +		anode->up = cpu_to_le32(node); +		if (fnod) +			anode->btree.flags |= BP_fnode_parent;  		mark_buffer_dirty(bh);  		brelse(bh);  	} @@ -232,27 +236,28 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi  		}  		btree = &fnode->btree;  	} -	ranode->up = node; -	memcpy(&ranode->btree, btree, 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++) { +	ranode->up = cpu_to_le32(node); +	memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free)); +	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, ranode->u.internal[n].down, &bh1))) { -			unode->up = ra; -			unode->btree.fnode_parent = 0; +		if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) { +			unode->up = cpu_to_le32(ra); +			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 = (char *)&btree->u.internal[2] - (char *)btree; -	btree->u.internal[0].file_secno = fs; -	btree->u.internal[0].down = ra; -	btree->u.internal[1].file_secno = -1; -	btree->u.internal[1].down = na; +	btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree); +	btree->u.internal[0].file_secno = cpu_to_le32(fs); +	btree->u.internal[0].down = cpu_to_le32(ra); +	btree->u.internal[1].file_secno = cpu_to_le32(-1); +	btree->u.internal[1].down = cpu_to_le32(na);  	mark_buffer_dirty(bh);  	brelse(bh);  	mark_buffer_dirty(bh2); @@ -278,8 +283,8 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)  	int d1, d2;  	go_down:  	d2 = 0; -	while (btree1->internal) { -		ano = btree1->u.internal[pos].down; +	while (bp_internal(btree1)) { +		ano = le32_to_cpu(btree1->u.internal[pos].down);  		if (level) brelse(bh);  		if (hpfs_sb(s)->sb_chk)  			if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1")) @@ -290,7 +295,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)  		pos = 0;  	}  	for (i = 0; i < btree1->n_used_nodes; i++) -		hpfs_free_sectors(s, btree1->u.external[i].disk_secno, btree1->u.external[i].length); +		hpfs_free_sectors(s, le32_to_cpu(btree1->u.external[i].disk_secno), le32_to_cpu(btree1->u.external[i].length));  	go_up:  	if (!level) return;  	brelse(bh); @@ -298,13 +303,13 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)  		if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return;  	hpfs_free_sectors(s, ano, 1);  	oano = ano; -	ano = anode->up; +	ano = le32_to_cpu(anode->up);  	if (--level) {  		if (!(anode = hpfs_map_anode(s, ano, &bh))) return;  		btree1 = &anode->btree;  	} else btree1 = btree;  	for (i = 0; i < btree1->n_used_nodes; i++) { -		if (btree1->u.internal[i].down == oano) { +		if (le32_to_cpu(btree1->u.internal[i].down) == oano) {  			if ((pos = i + 1) < btree1->n_used_nodes)  				goto go_down;  			else @@ -411,32 +416,32 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)  		if (fno) {  			btree->n_free_nodes = 8;  			btree->n_used_nodes = 0; -			btree->first_free = 8; -			btree->internal = 0; +			btree->first_free = cpu_to_le16(8); +			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 (btree->u.internal[i].file_secno >= secs) goto f; +			if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;  		brelse(bh);  		hpfs_error(s, "internal btree %08x doesn't end with -1", node);  		return;  		f:  		for (j = i + 1; j < btree->n_used_nodes; j++) -			hpfs_ea_remove(s, btree->u.internal[j].down, 1, 0); +			hpfs_ea_remove(s, le32_to_cpu(btree->u.internal[j].down), 1, 0);  		btree->n_used_nodes = i + 1;  		btree->n_free_nodes = nodes - btree->n_used_nodes; -		btree->first_free = 8 + 8 * btree->n_used_nodes; +		btree->first_free = cpu_to_le16(8 + 8 * btree->n_used_nodes);  		mark_buffer_dirty(bh); -		if (btree->u.internal[i].file_secno == secs) { +		if (btree->u.internal[i].file_secno == cpu_to_le32(secs)) {  			brelse(bh);  			return;  		} -		node = btree->u.internal[i].down; +		node = le32_to_cpu(btree->u.internal[i].down);  		brelse(bh);  		if (hpfs_sb(s)->sb_chk)  			if (hpfs_stop_cycles(s, node, &c1, &c2, "hpfs_truncate_btree")) @@ -446,25 +451,25 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)  	}	  	nodes = btree->n_used_nodes + btree->n_free_nodes;  	for (i = 0; i < btree->n_used_nodes; i++) -		if (btree->u.external[i].file_secno + btree->u.external[i].length >= secs) goto ff; +		if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) >= secs) goto ff;  	brelse(bh);  	return;  	ff: -	if (secs <= btree->u.external[i].file_secno) { +	if (secs <= le32_to_cpu(btree->u.external[i].file_secno)) {  		hpfs_error(s, "there is an allocation error in file %08x, sector %08x", f, secs);  		if (i) i--;  	} -	else if (btree->u.external[i].file_secno + btree->u.external[i].length > secs) { -		hpfs_free_sectors(s, btree->u.external[i].disk_secno + secs - -			btree->u.external[i].file_secno, btree->u.external[i].length -			- secs + btree->u.external[i].file_secno); /* I hope gcc optimizes this :-) */ -		btree->u.external[i].length = secs - btree->u.external[i].file_secno; +	else if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > secs) { +		hpfs_free_sectors(s, le32_to_cpu(btree->u.external[i].disk_secno) + secs - +			le32_to_cpu(btree->u.external[i].file_secno), le32_to_cpu(btree->u.external[i].length) +			- secs + le32_to_cpu(btree->u.external[i].file_secno)); /* I hope gcc optimizes this :-) */ +		btree->u.external[i].length = cpu_to_le32(secs - le32_to_cpu(btree->u.external[i].file_secno));  	}  	for (j = i + 1; j < btree->n_used_nodes; j++) -		hpfs_free_sectors(s, btree->u.external[j].disk_secno, btree->u.external[j].length); +		hpfs_free_sectors(s, le32_to_cpu(btree->u.external[j].disk_secno), le32_to_cpu(btree->u.external[j].length));  	btree->n_used_nodes = i + 1;  	btree->n_free_nodes = nodes - btree->n_used_nodes; -	btree->first_free = 8 + 12 * btree->n_used_nodes; +	btree->first_free = cpu_to_le16(8 + 12 * btree->n_used_nodes);  	mark_buffer_dirty(bh);  	brelse(bh);  } @@ -479,13 +484,13 @@ void hpfs_remove_fnode(struct super_block *s, fnode_secno fno)  	struct extended_attribute *ea;  	struct extended_attribute *ea_end;  	if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return; -	if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree); -	else hpfs_remove_dtree(s, fnode->u.external[0].disk_secno); +	if (!fnode_is_dir(fnode)) hpfs_remove_btree(s, &fnode->btree); +	else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno));  	ea_end = fnode_end_ea(fnode);  	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) -		if (ea->indirect) -			hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); -	hpfs_ea_ext_remove(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l); +		if (ea_indirect(ea)) +			hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea)); +	hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l));  	brelse(bh);  	hpfs_free_sectors(s, fno, 1);  } diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 793cb9d943d..8057fe4e657 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -7,22 +7,35 @@   */  #include <linux/sched.h>  #include <linux/slab.h> +#include <linux/blkdev.h>  #include "hpfs_fn.h" -void hpfs_lock_creation(struct super_block *s) +void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)  { -#ifdef DEBUG_LOCKS -	printk("lock creation\n"); -#endif -	mutex_lock(&hpfs_sb(s)->hpfs_creation_de); -} - -void hpfs_unlock_creation(struct super_block *s) -{ -#ifdef DEBUG_LOCKS -	printk("unlock creation\n"); -#endif -	mutex_unlock(&hpfs_sb(s)->hpfs_creation_de); +	struct buffer_head *bh; +	struct blk_plug plug; + +	if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size)) +		return; + +	bh = sb_find_get_block(s, secno); +	if (bh) { +		if (buffer_uptodate(bh)) { +			brelse(bh); +			return; +		} +		brelse(bh); +	}; + +	blk_start_plug(&plug); +	while (n > 0) { +		if (unlikely(secno >= hpfs_sb(s)->sb_fs_size)) +			break; +		sb_breadahead(s, secno); +		secno++; +		n--; +	} +	blk_finish_plug(&plug);  }  /* Map a sector into a buffer and return pointers to it and to the buffer. */ @@ -32,13 +45,17 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head  {  	struct buffer_head *bh; +	hpfs_lock_assert(s); + +	hpfs_prefetch_sectors(s, secno, ahead); +  	cond_resched();  	*bhp = bh = sb_bread(s, secno);  	if (bh != NULL)  		return bh->b_data;  	else { -		printk("HPFS: hpfs_map_sector: read error\n"); +		pr_err("%s(): read error\n", __func__);  		return NULL;  	}  } @@ -50,6 +67,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head  	struct buffer_head *bh;  	/*return hpfs_map_sector(s, secno, bhp, 0);*/ +	hpfs_lock_assert(s); +  	cond_resched();  	if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { @@ -57,7 +76,7 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head  		set_buffer_uptodate(bh);  		return bh->b_data;  	} else { -		printk("HPFS: hpfs_get_sector: getblk failed\n"); +		pr_err("%s(): getblk failed\n", __func__);  		return NULL;  	}  } @@ -67,44 +86,45 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head  void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh,  		   int ahead)  { -	struct buffer_head *bh;  	char *data; +	hpfs_lock_assert(s); +  	cond_resched();  	if (secno & 3) { -		printk("HPFS: hpfs_map_4sectors: unaligned read\n"); +		pr_err("%s(): unaligned read\n", __func__);  		return NULL;  	} -	qbh->data = data = kmalloc(2048, GFP_NOFS); -	if (!data) { -		printk("HPFS: hpfs_map_4sectors: out of memory\n"); -		goto bail; -	} +	hpfs_prefetch_sectors(s, secno, 4 + ahead); -	qbh->bh[0] = bh = sb_bread(s, secno); -	if (!bh) -		goto bail0; -	memcpy(data, bh->b_data, 512); +	if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0; +	if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1; +	if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2; +	if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3; -	qbh->bh[1] = bh = sb_bread(s, secno + 1); -	if (!bh) -		goto bail1; -	memcpy(data + 512, bh->b_data, 512); +	if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && +	    likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && +	    likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) { +		return qbh->data = qbh->bh[0]->b_data; +	} -	qbh->bh[2] = bh = sb_bread(s, secno + 2); -	if (!bh) -		goto bail2; -	memcpy(data + 2 * 512, bh->b_data, 512); +	qbh->data = data = kmalloc(2048, GFP_NOFS); +	if (!data) { +		pr_err("%s(): out of memory\n", __func__); +		goto bail4; +	} -	qbh->bh[3] = bh = sb_bread(s, secno + 3); -	if (!bh) -		goto bail3; -	memcpy(data + 3 * 512, bh->b_data, 512); +	memcpy(data + 0 * 512, qbh->bh[0]->b_data, 512); +	memcpy(data + 1 * 512, qbh->bh[1]->b_data, 512); +	memcpy(data + 2 * 512, qbh->bh[2]->b_data, 512); +	memcpy(data + 3 * 512, qbh->bh[3]->b_data, 512);  	return data; + bail4: +	brelse(qbh->bh[3]);   bail3:  	brelse(qbh->bh[2]);   bail2: @@ -112,9 +132,6 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe   bail1:  	brelse(qbh->bh[0]);   bail0: -	kfree(data); -	printk("HPFS: hpfs_map_4sectors: read error\n"); - bail:  	return NULL;  } @@ -125,50 +142,61 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,  {  	cond_resched(); +	hpfs_lock_assert(s); +  	if (secno & 3) { -		printk("HPFS: hpfs_get_4sectors: unaligned read\n"); +		pr_err("%s(): unaligned read\n", __func__);  		return NULL;  	} -	/*return hpfs_map_4sectors(s, secno, qbh, 0);*/ +	if (!hpfs_get_sector(s, secno + 0, &qbh->bh[0])) goto bail0; +	if (!hpfs_get_sector(s, secno + 1, &qbh->bh[1])) goto bail1; +	if (!hpfs_get_sector(s, secno + 2, &qbh->bh[2])) goto bail2; +	if (!hpfs_get_sector(s, secno + 3, &qbh->bh[3])) goto bail3; + +	if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && +	    likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && +	    likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) { +		return qbh->data = qbh->bh[0]->b_data; +	} +  	if (!(qbh->data = kmalloc(2048, GFP_NOFS))) { -		printk("HPFS: hpfs_get_4sectors: out of memory\n"); -		return NULL; +		pr_err("%s(): out of memory\n", __func__); +		goto bail4;  	} -	if (!(hpfs_get_sector(s, secno, &qbh->bh[0]))) goto bail0; -	if (!(hpfs_get_sector(s, secno + 1, &qbh->bh[1]))) goto bail1; -	if (!(hpfs_get_sector(s, secno + 2, &qbh->bh[2]))) goto bail2; -	if (!(hpfs_get_sector(s, secno + 3, &qbh->bh[3]))) goto bail3; -	memcpy(qbh->data, qbh->bh[0]->b_data, 512); -	memcpy(qbh->data + 512, qbh->bh[1]->b_data, 512); -	memcpy(qbh->data + 2*512, qbh->bh[2]->b_data, 512); -	memcpy(qbh->data + 3*512, qbh->bh[3]->b_data, 512);  	return qbh->data; -	bail3:	brelse(qbh->bh[2]); -	bail2:	brelse(qbh->bh[1]); -	bail1:	brelse(qbh->bh[0]); -	bail0: +bail4: +	brelse(qbh->bh[3]); +bail3: +	brelse(qbh->bh[2]); +bail2: +	brelse(qbh->bh[1]); +bail1: +	brelse(qbh->bh[0]); +bail0:  	return NULL;  }  void hpfs_brelse4(struct quad_buffer_head *qbh)  { -	brelse(qbh->bh[3]); -	brelse(qbh->bh[2]); -	brelse(qbh->bh[1]); +	if (unlikely(qbh->data != qbh->bh[0]->b_data)) +		kfree(qbh->data);  	brelse(qbh->bh[0]); -	kfree(qbh->data); +	brelse(qbh->bh[1]); +	brelse(qbh->bh[2]); +	brelse(qbh->bh[3]);  }	  void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh)  { -	PRINTK(("hpfs_mark_4buffers_dirty\n")); -	memcpy(qbh->bh[0]->b_data, qbh->data, 512); -	memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512); -	memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); -	memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); +	if (unlikely(qbh->data != qbh->bh[0]->b_data)) { +		memcpy(qbh->bh[0]->b_data, qbh->data + 0 * 512, 512); +		memcpy(qbh->bh[1]->b_data, qbh->data + 1 * 512, 512); +		memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); +		memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); +	}  	mark_buffer_dirty(qbh->bh[0]);  	mark_buffer_dirty(qbh->bh[1]);  	mark_buffer_dirty(qbh->bh[2]); diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c index 67d9d36b3d5..fa27980f222 100644 --- a/fs/hpfs/dentry.c +++ b/fs/hpfs/dentry.c @@ -12,7 +12,7 @@   * Note: the dentry argument is the parent dentry.   */ -static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr) +static int hpfs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)  {  	unsigned long	 hash;  	int		 i; @@ -34,29 +34,28 @@ static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)  	return 0;  } -static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) +static int hpfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +		unsigned int len, const char *str, const struct qstr *name)  { -	unsigned al=a->len; -	unsigned bl=b->len; -	hpfs_adjust_length(a->name, &al); +	unsigned al = len; +	unsigned bl = name->len; + +	hpfs_adjust_length(str, &al);  	/*hpfs_adjust_length(b->name, &bl);*/ -	/* 'a' is the qstr of an already existing dentry, so the name -	 * must be valid. 'b' must be validated first. + +	/* +	 * 'str' is the nane of an already existing dentry, so the name +	 * must be valid. 'name' must be validated first.  	 */ -	if (hpfs_chk_name(b->name, &bl)) +	if (hpfs_chk_name(name->name, &bl))  		return 1; -	if (hpfs_compare_names(dentry->d_sb, a->name, al, b->name, bl, 0)) +	if (hpfs_compare_names(parent->d_sb, str, al, name->name, bl, 0))  		return 1;  	return 0;  } -static const struct dentry_operations hpfs_dentry_operations = { +const struct dentry_operations hpfs_dentry_operations = {  	.d_hash		= hpfs_hash_dentry,  	.d_compare	= hpfs_compare_dentry,  }; - -void hpfs_set_dentry_operations(struct dentry *dentry) -{ -	dentry->d_op = &hpfs_dentry_operations; -} diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 2338130cceb..2a8e07425de 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -6,16 +6,15 @@   *  directory VFS functions   */ -#include <linux/smp_lock.h>  #include <linux/slab.h>  #include "hpfs_fn.h"  static int hpfs_dir_release(struct inode *inode, struct file *filp)  { -	lock_kernel(); +	hpfs_lock(inode->i_sb);  	hpfs_del_pos(inode, &filp->f_pos);  	/*hpfs_write_if_changed(inode);*/ -	unlock_kernel(); +	hpfs_unlock(inode->i_sb);  	return 0;  } @@ -26,45 +25,51 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)  	loff_t new_off = off + (whence == 1 ? filp->f_pos : 0);  	loff_t pos;  	struct quad_buffer_head qbh; -	struct inode *i = filp->f_path.dentry->d_inode; +	struct inode *i = file_inode(filp);  	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);  	struct super_block *s = i->i_sb; -	lock_kernel(); +	/* Somebody else will have to figure out what to do here */ +	if (whence == SEEK_DATA || whence == SEEK_HOLE) +		return -EINVAL; -	/*printk("dir lseek\n");*/ -	if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;  	mutex_lock(&i->i_mutex); +	hpfs_lock(s); + +	/*pr_info("dir lseek\n");*/ +	if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;  	pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;  	while (pos != new_off) {  		if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);  		else goto fail;  		if (pos == 12) goto fail;  	} -	mutex_unlock(&i->i_mutex); +	hpfs_add_pos(i, &filp->f_pos);  ok: -	unlock_kernel(); -	return filp->f_pos = new_off; +	filp->f_pos = new_off; +	hpfs_unlock(s); +	mutex_unlock(&i->i_mutex); +	return new_off;  fail: +	/*pr_warn("illegal lseek: %016llx\n", new_off);*/ +	hpfs_unlock(s);  	mutex_unlock(&i->i_mutex); -	/*printk("illegal lseek: %016llx\n", new_off);*/ -	unlock_kernel();  	return -ESPIPE;  } -static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) +static int hpfs_readdir(struct file *file, struct dir_context *ctx)  { -	struct inode *inode = filp->f_path.dentry->d_inode; +	struct inode *inode = file_inode(file);  	struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);  	struct quad_buffer_head qbh;  	struct hpfs_dirent *de;  	int lc; -	long old_pos; +	loff_t next_pos;  	unsigned char *tempname;  	int c1, c2 = 0;  	int ret = 0; -	lock_kernel(); +	hpfs_lock(inode->i_sb);  	if (hpfs_sb(inode->i_sb)->sb_chk) {  		if (hpfs_chk_sectors(inode->i_sb, inode->i_ino, 1, "dir_fnode")) { @@ -84,14 +89,14 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  			ret = -EIOERROR;  			goto out;  		} -		if (!fno->dirflag) { +		if (!fnode_is_dir(fno)) {  			e = 1;  			hpfs_error(inode->i_sb, "not a directory, fnode %08lx",  					(unsigned long)inode->i_ino);  		} -		if (hpfs_inode->i_dno != fno->u.external[0].disk_secno) { +		if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) {  			e = 1; -			hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, fno->u.external[0].disk_secno); +			hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, le32_to_cpu(fno->u.external[0].disk_secno));  		}  		brelse(bh);  		if (e) { @@ -100,11 +105,11 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  		}  	}  	lc = hpfs_sb(inode->i_sb)->sb_lowercase; -	if (filp->f_pos == 12) { /* diff -r requires this (note, that diff -r */ -		filp->f_pos = 13; /* also fails on msdos filesystem in 2.0) */ +	if (ctx->pos == 12) { /* diff -r requires this (note, that diff -r */ +		ctx->pos = 13; /* also fails on msdos filesystem in 2.0) */  		goto out;  	} -	if (filp->f_pos == 13) { +	if (ctx->pos == 13) {  		ret = -ENOENT;  		goto out;  	} @@ -115,33 +120,34 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  		   accepted by filldir, but what can I do?  		   maybe killall -9 ls helps */  		if (hpfs_sb(inode->i_sb)->sb_chk) -			if (hpfs_stop_cycles(inode->i_sb, filp->f_pos, &c1, &c2, "hpfs_readdir")) { +			if (hpfs_stop_cycles(inode->i_sb, ctx->pos, &c1, &c2, "hpfs_readdir")) {  				ret = -EFSERROR;  				goto out;  			} -		if (filp->f_pos == 12) +		if (ctx->pos == 12)  			goto out; -		if (filp->f_pos == 3 || filp->f_pos == 4 || filp->f_pos == 5) { -			printk("HPFS: warning: pos==%d\n",(int)filp->f_pos); +		if (ctx->pos == 3 || ctx->pos == 4 || ctx->pos == 5) { +			pr_err("pos==%d\n", (int)ctx->pos);  			goto out;  		} -		if (filp->f_pos == 0) { -			if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) +		if (ctx->pos == 0) { +			if (!dir_emit_dot(file, ctx))  				goto out; -			filp->f_pos = 11; +			ctx->pos = 11;  		} -		if (filp->f_pos == 11) { -			if (filldir(dirent, "..", 2, filp->f_pos, hpfs_inode->i_parent_dir, DT_DIR) < 0) +		if (ctx->pos == 11) { +			if (!dir_emit(ctx, "..", 2, hpfs_inode->i_parent_dir, DT_DIR))  				goto out; -			filp->f_pos = 1; +			ctx->pos = 1;  		} -		if (filp->f_pos == 1) { -			filp->f_pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1; -			hpfs_add_pos(inode, &filp->f_pos); -			filp->f_version = inode->i_version; +		if (ctx->pos == 1) { +			ctx->pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1; +			hpfs_add_pos(inode, &file->f_pos); +			file->f_version = inode->i_version;  		} -		old_pos = filp->f_pos; -		if (!(de = map_pos_dirent(inode, &filp->f_pos, &qbh))) { +		next_pos = ctx->pos; +		if (!(de = map_pos_dirent(inode, &next_pos, &qbh))) { +			ctx->pos = next_pos;  			ret = -EIOERROR;  			goto out;  		} @@ -149,25 +155,26 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)  			if (hpfs_sb(inode->i_sb)->sb_chk) {  				if (de->first && !de->last && (de->namelen != 2  				    || de ->name[0] != 1 || de->name[1] != 1)) -					hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", old_pos); +					hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08lx", (unsigned long)ctx->pos);  				if (de->last && (de->namelen != 1 || de ->name[0] != 255)) -					hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", old_pos); +					hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08lx", (unsigned long)ctx->pos);  			}  			hpfs_brelse4(&qbh); +			ctx->pos = next_pos;  			goto again;  		}  		tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); -		if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) { -			filp->f_pos = old_pos; +		if (!dir_emit(ctx, tempname, de->namelen, le32_to_cpu(de->fnode), DT_UNKNOWN)) {  			if (tempname != de->name) kfree(tempname);  			hpfs_brelse4(&qbh);  			goto out;  		} +		ctx->pos = next_pos;  		if (tempname != de->name) kfree(tempname);  		hpfs_brelse4(&qbh);  	}  out: -	unlock_kernel(); +	hpfs_unlock(inode->i_sb);  	return ret;  } @@ -186,7 +193,7 @@ out:   *	      to tell read_inode to read fnode or not.   */ -struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)  {  	const unsigned char *name = dentry->d_name.name;  	unsigned len = dentry->d_name.len; @@ -197,10 +204,10 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name  	struct inode *result = NULL;  	struct hpfs_inode_info *hpfs_result; -	lock_kernel(); +	hpfs_lock(dir->i_sb);  	if ((err = hpfs_chk_name(name, &len))) {  		if (err == -ENAMETOOLONG) { -			unlock_kernel(); +			hpfs_unlock(dir->i_sb);  			return ERR_PTR(-ENAMETOOLONG);  		}  		goto end_add; @@ -222,7 +229,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name  	 * Get inode number, what we're after.  	 */ -	ino = de->fnode; +	ino = le32_to_cpu(de->fnode);  	/*  	 * Go find or make an inode. @@ -237,22 +244,20 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name  		hpfs_init_inode(result);  		if (de->directory)  			hpfs_read_inode(result); -		else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas) +		else if (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas)  			hpfs_read_inode(result);  		else {  			result->i_mode |= S_IFREG;  			result->i_mode &= ~0111;  			result->i_op = &hpfs_file_iops;  			result->i_fop = &hpfs_file_ops; -			result->i_nlink = 1; +			set_nlink(result, 1);  		}  		unlock_new_inode(result);  	}  	hpfs_result = hpfs_i(result);  	if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino; -	hpfs_decide_conv(result, name, len); -  	if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {  		hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");  		goto bail1; @@ -264,19 +269,19 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name  	 */  	if (!result->i_ctime.tv_sec) { -		if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date))) +		if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date))))  			result->i_ctime.tv_sec = 1;  		result->i_ctime.tv_nsec = 0; -		result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date); +		result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date));  		result->i_mtime.tv_nsec = 0; -		result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date); +		result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date));  		result->i_atime.tv_nsec = 0; -		hpfs_result->i_ea_size = de->ea_size; +		hpfs_result->i_ea_size = le32_to_cpu(de->ea_size);  		if (!hpfs_result->i_ea_mode && de->read_only)  			result->i_mode &= ~0222;  		if (!de->directory) {  			if (result->i_size == -1) { -				result->i_size = de->file_size; +				result->i_size = le32_to_cpu(de->file_size);  				result->i_data.a_ops = &hpfs_aops;  				hpfs_i(result)->mmu_private = result->i_size;  			/* @@ -298,8 +303,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name  	end:  	end_add: -	hpfs_set_dentry_operations(dentry); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	d_add(dentry, result);  	return NULL; @@ -312,7 +316,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name  	/*bail:*/ -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return ERR_PTR(-ENOENT);  } @@ -320,7 +324,7 @@ const struct file_operations hpfs_dir_ops =  {  	.llseek		= hpfs_dir_lseek,  	.read		= generic_read_dir, -	.readdir	= hpfs_readdir, +	.iterate	= hpfs_readdir,  	.release	= hpfs_dir_release,  	.fsync		= hpfs_file_fsync,  }; diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index 9b2ffadfc8c..f36fc010fcc 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -14,11 +14,11 @@ static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde)  	struct hpfs_dirent *de_end = dnode_end_de(d);  	int i = 1;  	for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { -		if (de == fde) return ((loff_t) d->self << 4) | (loff_t)i; +		if (de == fde) return ((loff_t) le32_to_cpu(d->self) << 4) | (loff_t)i;  		i++;  	} -	printk("HPFS: get_pos: not_found\n"); -	return ((loff_t)d->self << 4) | (loff_t)1; +	pr_info("%s(): not_found\n", __func__); +	return ((loff_t)le32_to_cpu(d->self) << 4) | (loff_t)1;  }  void hpfs_add_pos(struct inode *inode, loff_t *pos) @@ -32,7 +32,7 @@ void hpfs_add_pos(struct inode *inode, loff_t *pos)  			if (hpfs_inode->i_rddir_off[i] == pos) return;  	if (!(i&0x0f)) {  		if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) { -			printk("HPFS: out of memory for position list\n"); +			pr_err("out of memory for position list\n");  			return;  		}  		if (hpfs_inode->i_rddir_off) { @@ -63,7 +63,8 @@ void hpfs_del_pos(struct inode *inode, loff_t *pos)  	}  	return;  	not_f: -	/*printk("HPFS: warning: position pointer %p->%08x not found\n", pos, (int)*pos);*/ +	/*pr_warn("position pointer %p->%08x not found\n", +		  pos, (int)*pos);*/  	return;  } @@ -92,8 +93,11 @@ static void hpfs_pos_ins(loff_t *p, loff_t d, loff_t c)  {  	if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) {  		int n = (*p & 0x3f) + c; -		if (n > 0x3f) printk("HPFS: hpfs_pos_ins: %08x + %d\n", (int)*p, (int)c >> 8); -		else *p = (*p & ~0x3f) | n; +		if (n > 0x3f) +			pr_err("%s(): %08x + %d\n", +				__func__, (int)*p, (int)c >> 8); +		else +			*p = (*p & ~0x3f) | n;  	}  } @@ -101,8 +105,11 @@ static void hpfs_pos_del(loff_t *p, loff_t d, loff_t c)  {  	if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) {  		int n = (*p & 0x3f) - c; -		if (n < 1) printk("HPFS: hpfs_pos_ins: %08x - %d\n", (int)*p, (int)c >> 8); -		else *p = (*p & ~0x3f) | n; +		if (n < 1) +			pr_err("%s(): %08x - %d\n", +				__func__, (int)*p, (int)c >> 8); +		else +			*p = (*p & ~0x3f) | n;  	}  } @@ -130,29 +137,30 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno  {  	struct hpfs_dirent *de;  	if (!(de = dnode_last_de(d))) { -		hpfs_error(s, "set_last_pointer: empty dnode %08x", d->self); +		hpfs_error(s, "set_last_pointer: empty dnode %08x", le32_to_cpu(d->self));  		return;  	}  	if (hpfs_sb(s)->sb_chk) {  		if (de->down) {  			hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x", -				d->self, de_down_pointer(de)); +				le32_to_cpu(d->self), de_down_pointer(de));  			return;  		} -		if (de->length != 32) { -			hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", d->self); +		if (le16_to_cpu(de->length) != 32) { +			hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", le32_to_cpu(d->self));  			return;  		}  	}  	if (ptr) { -		if ((d->first_free += 4) > 2048) { -			hpfs_error(s,"set_last_pointer: too long dnode %08x", d->self); -			d->first_free -= 4; +		le32_add_cpu(&d->first_free, 4); +		if (le32_to_cpu(d->first_free) > 2048) { +			hpfs_error(s, "set_last_pointer: too long dnode %08x", le32_to_cpu(d->self)); +			le32_add_cpu(&d->first_free, -4);  			return;  		} -		de->length = 36; +		de->length = cpu_to_le16(36);  		de->down = 1; -		*(dnode_secno *)((char *)de + 32) = ptr; +		*(__le32 *)((char *)de + 32) = cpu_to_le32(ptr);  	}  } @@ -168,7 +176,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,  	for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {  		int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last);  		if (!c) { -			hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, d->self); +			hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, le32_to_cpu(d->self));  			return NULL;  		}  		if (c < 0) break; @@ -176,15 +184,14 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,  	memmove((char *)de + d_size, de, (char *)de_end - (char *)de);  	memset(de, 0, d_size);  	if (down_ptr) { -		*(int *)((char *)de + d_size - 4) = down_ptr; +		*(__le32 *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr);  		de->down = 1;  	} -	de->length = d_size; -	if (down_ptr) de->down = 1; +	de->length = cpu_to_le16(d_size);  	de->not_8x3 = hpfs_is_name_long(name, namelen);  	de->namelen = namelen;  	memcpy(de->name, name, namelen); -	d->first_free += d_size; +	le32_add_cpu(&d->first_free, d_size);  	return de;  } @@ -194,25 +201,25 @@ static void hpfs_delete_de(struct super_block *s, struct dnode *d,  			   struct hpfs_dirent *de)  {  	if (de->last) { -		hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self); +		hpfs_error(s, "attempt to delete last dirent in dnode %08x", le32_to_cpu(d->self));  		return;  	} -	d->first_free -= de->length; -	memmove(de, de_next_de(de), d->first_free + (char *)d - (char *)de); +	d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - le16_to_cpu(de->length)); +	memmove(de, de_next_de(de), le32_to_cpu(d->first_free) + (char *)d - (char *)de);  }  static void fix_up_ptrs(struct super_block *s, struct dnode *d)  {  	struct hpfs_dirent *de;  	struct hpfs_dirent *de_end = dnode_end_de(d); -	dnode_secno dno = d->self; +	dnode_secno dno = le32_to_cpu(d->self);  	for (de = dnode_first_de(d); de < de_end; de = de_next_de(de))  		if (de->down) {  			struct quad_buffer_head qbh;  			struct dnode *dd;  			if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) { -				if (dd->up != dno || dd->root_dnode) { -					dd->up = dno; +				if (le32_to_cpu(dd->up) != dno || dd->root_dnode) { +					dd->up = cpu_to_le32(dno);  					dd->root_dnode = 0;  					hpfs_mark_4buffers_dirty(&qbh);  				} @@ -239,12 +246,12 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  	struct fnode *fnode;  	int c1, c2 = 0;  	if (!(nname = kmalloc(256, GFP_NOFS))) { -		printk("HPFS: out of memory, can't add to dnode\n"); +		pr_err("out of memory, can't add to dnode\n");  		return 1;  	}  	go_up:  	if (namelen >= 256) { -		hpfs_error(i->i_sb, "hpfs_add_to_dnode: namelen == %d", namelen); +		hpfs_error(i->i_sb, "%s(): namelen == %d", __func__, namelen);  		kfree(nd);  		kfree(nname);  		return 1; @@ -262,7 +269,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  			kfree(nname);  			return 1;  		} -	if (d->first_free + de_size(namelen, down_ptr) <= 2048) { +	if (le32_to_cpu(d->first_free) + de_size(namelen, down_ptr) <= 2048) {  		loff_t t;  		copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de);  		t = get_pos(d, de); @@ -281,16 +288,16 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  		   not be any error while splitting dnodes, otherwise the  		   whole directory, not only file we're adding, would  		   be lost. */ -		printk("HPFS: out of memory for dnode splitting\n"); +		pr_err("out of memory for dnode splitting\n");  		hpfs_brelse4(&qbh);  		kfree(nname);  		return 1;  	}	 -	memcpy(nd, d, d->first_free); +	memcpy(nd, d, le32_to_cpu(d->first_free));  	copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de);  	for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1);  	h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10; -	if (!(ad = hpfs_alloc_dnode(i->i_sb, d->up, &adno, &qbh1, 0))) { +	if (!(ad = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &adno, &qbh1))) {  		hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");  		hpfs_brelse4(&qbh);  		kfree(nd); @@ -313,20 +320,21 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  	down_ptr = adno;  	set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);  	de = de_next_de(de); -	memmove((char *)nd + 20, de, nd->first_free + (char *)nd - (char *)de); -	nd->first_free -= (char *)de - (char *)nd - 20; -	memcpy(d, nd, nd->first_free); +	memmove((char *)nd + 20, de, le32_to_cpu(nd->first_free) + (char *)nd - (char *)de); +	le32_add_cpu(&nd->first_free, -((char *)de - (char *)nd - 20)); +	memcpy(d, nd, le32_to_cpu(nd->first_free));  	for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos);  	fix_up_ptrs(i->i_sb, ad);  	if (!d->root_dnode) { -		dno = ad->up = d->up; +		ad->up = d->up; +		dno = le32_to_cpu(ad->up);  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh);  		hpfs_mark_4buffers_dirty(&qbh1);  		hpfs_brelse4(&qbh1);  		goto go_up;  	} -	if (!(rd = hpfs_alloc_dnode(i->i_sb, d->up, &rdno, &qbh2, 0))) { +	if (!(rd = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &rdno, &qbh2))) {  		hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");  		hpfs_brelse4(&qbh);  		hpfs_brelse4(&qbh1); @@ -338,7 +346,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  	i->i_blocks += 4;  	rd->root_dnode = 1;  	rd->up = d->up; -	if (!(fnode = hpfs_map_fnode(i->i_sb, d->up, &bh))) { +	if (!(fnode = hpfs_map_fnode(i->i_sb, le32_to_cpu(d->up), &bh))) {  		hpfs_free_dnode(i->i_sb, rdno);  		hpfs_brelse4(&qbh);  		hpfs_brelse4(&qbh1); @@ -347,10 +355,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  		kfree(nname);  		return 1;  	} -	fnode->u.external[0].disk_secno = rdno; +	fnode->u.external[0].disk_secno = cpu_to_le32(rdno);  	mark_buffer_dirty(bh);  	brelse(bh); -	d->up = ad->up = hpfs_i(i)->i_dno = rdno; +	hpfs_i(i)->i_dno = rdno; +	d->up = ad->up = cpu_to_le32(rdno);  	d->root_dnode = ad->root_dnode = 0;  	hpfs_mark_4buffers_dirty(&qbh);  	hpfs_brelse4(&qbh); @@ -373,7 +382,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,  int hpfs_add_dirent(struct inode *i,  		    const unsigned char *name, unsigned namelen, -		    struct hpfs_dirent *new_de, int cdepth) +		    struct hpfs_dirent *new_de)  {  	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);  	struct dnode *d; @@ -403,7 +412,6 @@ int hpfs_add_dirent(struct inode *i,  		}  	}  	hpfs_brelse4(&qbh); -	if (!cdepth) hpfs_lock_creation(i->i_sb);  	if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) {  		c = 1;  		goto ret; @@ -411,7 +419,6 @@ int hpfs_add_dirent(struct inode *i,  	i->i_version++;  	c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0);  	ret: -	if (!cdepth) hpfs_unlock_creation(i->i_sb);  	return c;  } @@ -437,9 +444,9 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)  				return 0;  		if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0;  		if (hpfs_sb(i->i_sb)->sb_chk) { -			if (dnode->up != chk_up) { +			if (le32_to_cpu(dnode->up) != chk_up) {  				hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x", -					dno, chk_up, dnode->up); +					dno, chk_up, le32_to_cpu(dnode->up));  				hpfs_brelse4(&qbh);  				return 0;  			} @@ -455,7 +462,7 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)  		hpfs_brelse4(&qbh);  	}  	while (!(de = dnode_pre_last_de(dnode))) { -		dnode_secno up = dnode->up; +		dnode_secno up = le32_to_cpu(dnode->up);  		hpfs_brelse4(&qbh);  		hpfs_free_dnode(i->i_sb, dno);  		i->i_size -= 2048; @@ -474,8 +481,8 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)  			hpfs_brelse4(&qbh);  			return 0;  		} -		dnode->first_free -= 4; -		de->length -= 4; +		le32_add_cpu(&dnode->first_free, -4); +		le16_add_cpu(&de->length, -4);  		de->down = 0;  		hpfs_mark_4buffers_dirty(&qbh);  		dno = up; @@ -483,12 +490,12 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)  	t = get_pos(dnode, de);  	for_all_poss(i, hpfs_pos_subst, t, 4);  	for_all_poss(i, hpfs_pos_subst, t + 1, 5); -	if (!(nde = kmalloc(de->length, GFP_NOFS))) { +	if (!(nde = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) {  		hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted");  		hpfs_brelse4(&qbh);  		return 0;  	} -	memcpy(nde, de, de->length); +	memcpy(nde, de, le16_to_cpu(de->length));  	ddno = de->down ? de_down_pointer(de) : 0;  	hpfs_delete_de(i->i_sb, dnode, de);  	set_last_pointer(i->i_sb, dnode, ddno); @@ -517,11 +524,11 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)  	try_it_again:  	if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return;  	if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return; -	if (dnode->first_free > 56) goto end; -	if (dnode->first_free == 52 || dnode->first_free == 56) { +	if (le32_to_cpu(dnode->first_free) > 56) goto end; +	if (le32_to_cpu(dnode->first_free) == 52 || le32_to_cpu(dnode->first_free) == 56) {  		struct hpfs_dirent *de_end;  		int root = dnode->root_dnode; -		up = dnode->up; +		up = le32_to_cpu(dnode->up);  		de = dnode_first_de(dnode);  		down = de->down ? de_down_pointer(de) : 0;  		if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) { @@ -545,13 +552,13 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)  				return;  			    }  			if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { -				d1->up = up; +				d1->up = cpu_to_le32(up);  				d1->root_dnode = 1;  				hpfs_mark_4buffers_dirty(&qbh1);  				hpfs_brelse4(&qbh1);  			}  			if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) { -				fnode->u.external[0].disk_secno = down; +				fnode->u.external[0].disk_secno = cpu_to_le32(down);  				mark_buffer_dirty(bh);  				brelse(bh);  			} @@ -570,22 +577,22 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)  		for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p);  		if (!down) {  			de->down = 0; -			de->length -= 4; -			dnode->first_free -= 4; +			le16_add_cpu(&de->length, -4); +			le32_add_cpu(&dnode->first_free, -4);  			memmove(de_next_de(de), (char *)de_next_de(de) + 4, -				(char *)dnode + dnode->first_free - (char *)de_next_de(de)); +				(char *)dnode + le32_to_cpu(dnode->first_free) - (char *)de_next_de(de));  		} else {  			struct dnode *d1;  			struct quad_buffer_head qbh1; -			*(dnode_secno *) ((void *) de + de->length - 4) = down; +			*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4) = down;  			if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { -				d1->up = up; +				d1->up = cpu_to_le32(up);  				hpfs_mark_4buffers_dirty(&qbh1);  				hpfs_brelse4(&qbh1);  			}  		}  	} else { -		hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, dnode->first_free); +		hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, le32_to_cpu(dnode->first_free));  		goto end;  	} @@ -596,23 +603,24 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)  		struct quad_buffer_head qbh1;  		if (!de_next->down) goto endm;  		ndown = de_down_pointer(de_next); -		if (!(de_cp = kmalloc(de->length, GFP_NOFS))) { -			printk("HPFS: out of memory for dtree balancing\n"); +		if (!(de_cp = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) { +			pr_err("out of memory for dtree balancing\n");  			goto endm;  		} -		memcpy(de_cp, de, de->length); +		memcpy(de_cp, de, le16_to_cpu(de->length));  		hpfs_delete_de(i->i_sb, dnode, de);  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh);  		for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4);  		for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1);  		if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) { -			d1->up = ndown; +			d1->up = cpu_to_le32(ndown);  			hpfs_mark_4buffers_dirty(&qbh1);  			hpfs_brelse4(&qbh1);  		}  		hpfs_add_to_dnode(i, ndown, de_cp->name, de_cp->namelen, de_cp, de_cp->down ? de_down_pointer(de_cp) : 0); -		/*printk("UP-TO-DNODE: %08x (ndown = %08x, down = %08x, dno = %08x)\n", up, ndown, down, dno);*/ +		/*pr_info("UP-TO-DNODE: %08x (ndown = %08x, down = %08x, dno = %08x)\n", +		  up, ndown, down, dno);*/  		dno = up;  		kfree(de_cp);  		goto try_it_again; @@ -635,50 +643,50 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)  			struct hpfs_dirent *del = dnode_last_de(d1);  			dlp = del->down ? de_down_pointer(del) : 0;  			if (!dlp && down) { -				if (d1->first_free > 2044) { +				if (le32_to_cpu(d1->first_free) > 2044) {  					if (hpfs_sb(i->i_sb)->sb_chk >= 2) { -						printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); -						printk("HPFS: warning: terminating balancing operation\n"); +						pr_err("unbalanced dnode tree, see hpfs.txt 4 more info\n"); +						pr_err("terminating balancing operation\n");  					}  					hpfs_brelse4(&qbh1);  					goto endm;  				}  				if (hpfs_sb(i->i_sb)->sb_chk >= 2) { -					printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); -					printk("HPFS: warning: goin'on\n"); +					pr_err("unbalanced dnode tree, see hpfs.txt 4 more info\n"); +					pr_err("goin'on\n");  				} -				del->length += 4; +				le16_add_cpu(&del->length, 4);  				del->down = 1; -				d1->first_free += 4; +				le32_add_cpu(&d1->first_free, 4);  			}  			if (dlp && !down) { -				del->length -= 4; +				le16_add_cpu(&del->length, -4);  				del->down = 0; -				d1->first_free -= 4; +				le32_add_cpu(&d1->first_free, -4);  			} else if (down) -				*(dnode_secno *) ((void *) del + del->length - 4) = down; +				*(__le32 *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down);  		} else goto endm; -		if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) { -			printk("HPFS: out of memory for dtree balancing\n"); +		if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) { +			pr_err("out of memory for dtree balancing\n");  			hpfs_brelse4(&qbh1);  			goto endm;  		}  		hpfs_mark_4buffers_dirty(&qbh1);  		hpfs_brelse4(&qbh1); -		memcpy(de_cp, de_prev, de_prev->length); +		memcpy(de_cp, de_prev, le16_to_cpu(de_prev->length));  		hpfs_delete_de(i->i_sb, dnode, de_prev);  		if (!de_prev->down) { -			de_prev->length += 4; +			le16_add_cpu(&de_prev->length, 4);  			de_prev->down = 1; -			dnode->first_free += 4; +			le32_add_cpu(&dnode->first_free, 4);  		} -		*(dnode_secno *) ((void *) de_prev + de_prev->length - 4) = ndown; +		*(__le32 *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown);  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh);  		for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4);  		for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1));  		if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) { -			d1->up = ndown; +			d1->up = cpu_to_le32(ndown);  			hpfs_mark_4buffers_dirty(&qbh1);  			hpfs_brelse4(&qbh1);  		} @@ -701,7 +709,6 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,  {  	struct dnode *dnode = qbh->data;  	dnode_secno down = 0; -	int lock = 0;  	loff_t t;  	if (de->first || de->last) {  		hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno); @@ -710,11 +717,8 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,  	}  	if (de->down) down = de_down_pointer(de);  	if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) { -		lock = 1; -		hpfs_lock_creation(i->i_sb);  		if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) {  			hpfs_brelse4(qbh); -			hpfs_unlock_creation(i->i_sb);  			return 2;  		}  	} @@ -727,11 +731,9 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,  		dnode_secno a = move_to_top(i, down, dno);  		for_all_poss(i, hpfs_pos_subst, 5, t);  		if (a) delete_empty_dnode(i, a); -		if (lock) hpfs_unlock_creation(i->i_sb);  		return !a;  	}  	delete_empty_dnode(i, dno); -	if (lock) hpfs_unlock_creation(i->i_sb);  	return 0;  } @@ -751,8 +753,8 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,  	ptr = 0;  	go_up:  	if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return; -	if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && dnode->up != odno) -		hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, dnode->up); +	if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && le32_to_cpu(dnode->up) != odno) +		hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, le32_to_cpu(dnode->up));  	de = dnode_first_de(dnode);  	if (ptr) while(1) {  		if (de->down) if (de_down_pointer(de) == ptr) goto process_de; @@ -776,7 +778,7 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,  	if (!de->first && !de->last && n_items) (*n_items)++;  	if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de;  	ptr = dno; -	dno = dnode->up; +	dno = le32_to_cpu(dnode->up);  	if (dnode->root_dnode) {  		hpfs_brelse4(&qbh);  		return; @@ -824,8 +826,8 @@ dnode_secno hpfs_de_as_down_as_possible(struct super_block *s, dnode_secno dno)  			return d;  	if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno;  	if (hpfs_sb(s)->sb_chk) -		if (up && ((struct dnode *)qbh.data)->up != up) -			hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, ((struct dnode *)qbh.data)->up); +		if (up && le32_to_cpu(((struct dnode *)qbh.data)->up) != up) +			hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, le32_to_cpu(((struct dnode *)qbh.data)->up));  	if (!de->down) {  		hpfs_brelse4(&qbh);  		return d; @@ -874,7 +876,7 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,  	/* Going up */  	if (dnode->root_dnode) goto bail; -	if (!(up_dnode = hpfs_map_dnode(inode->i_sb, dnode->up, &qbh0))) +	if (!(up_dnode = hpfs_map_dnode(inode->i_sb, le32_to_cpu(dnode->up), &qbh0)))  		goto bail;  	end_up_de = dnode_end_de(up_dnode); @@ -882,16 +884,16 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,  	for (up_de = dnode_first_de(up_dnode); up_de < end_up_de;  	     up_de = de_next_de(up_de)) {  		if (!(++c & 077)) hpfs_error(inode->i_sb, -			"map_pos_dirent: pos crossed dnode boundary; dnode = %08x", dnode->up); +			"map_pos_dirent: pos crossed dnode boundary; dnode = %08x", le32_to_cpu(dnode->up));  		if (up_de->down && de_down_pointer(up_de) == dno) { -			*posp = ((loff_t) dnode->up << 4) + c; +			*posp = ((loff_t) le32_to_cpu(dnode->up) << 4) + c;  			hpfs_brelse4(&qbh0);  			return de;  		}  	}  	hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x", -		dno, dnode->up); +		dno, le32_to_cpu(dnode->up));  	hpfs_brelse4(&qbh0);  	bail: @@ -1006,7 +1008,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,  	int d1, d2 = 0;  	name1 = f->name;  	if (!(name2 = kmalloc(256, GFP_NOFS))) { -		printk("HPFS: out of memory, can't map dirent\n"); +		pr_err("out of memory, can't map dirent\n");  		return NULL;  	}  	if (f->len <= 15) @@ -1017,17 +1019,17 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,  		/*name2[15] = 0xff;*/  		name1len = 15; name2len = 256;  	} -	if (!(upf = hpfs_map_fnode(s, f->up, &bh))) { +	if (!(upf = hpfs_map_fnode(s, le32_to_cpu(f->up), &bh))) {  		kfree(name2);  		return NULL;  	}	 -	if (!upf->dirflag) { +	if (!fnode_is_dir(upf)) {  		brelse(bh); -		hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, f->up); +		hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up));  		kfree(name2);  		return NULL;  	} -	dno = upf->u.external[0].disk_secno; +	dno = le32_to_cpu(upf->u.external[0].disk_secno);  	brelse(bh);  	go_down:  	downd = 0; @@ -1049,7 +1051,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,  		return NULL;  	}  	next_de: -	if (de->fnode == fno) { +	if (le32_to_cpu(de->fnode) == fno) {  		kfree(name2);  		return de;  	} @@ -1065,7 +1067,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,  		goto go_down;  	}  	f: -	if (de->fnode == fno) { +	if (le32_to_cpu(de->fnode) == fno) {  		kfree(name2);  		return de;  	} @@ -1074,7 +1076,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,  	if ((de = de_next_de(de)) < de_end) goto next_de;  	if (d->root_dnode) goto not_found;  	downd = dno; -	dno = d->up; +	dno = le32_to_cpu(d->up);  	hpfs_brelse4(qbh);  	if (hpfs_sb(s)->sb_chk)  		if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) { diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 45e53d972b4..ce3f98ba993 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c @@ -23,17 +23,17 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)  			return;  		}  		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; -		if (ea->indirect) { -			if (ea->valuelen != 8) { -				hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x", +		if (ea_indirect(ea)) { +			if (ea_valuelen(ea) != 8) { +				hpfs_error(s, "ea_indirect(ea) set while ea->valuelen!=8, %s %08x, pos %08x",  					ano ? "anode" : "sectors", a, pos);  				return;  			}  			if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))  				return; -			hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); +			hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea));  		} -		pos += ea->namelen + ea->valuelen + 5; +		pos += ea->namelen + ea_valuelen(ea) + 5;  	}  	if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9);  	else { @@ -51,7 +51,7 @@ static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)  {  	char *ret;  	if (!(ret = kmalloc(size + 1, GFP_NOFS))) { -		printk("HPFS: out of memory for EA\n"); +		pr_err("out of memory for EA\n");  		return NULL;  	}  	if (hpfs_ea_read(s, a, ano, 0, size, ret)) { @@ -76,24 +76,24 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,  	unsigned pos;  	int ano, len;  	secno a; +	char ex[4 + 255 + 1 + 8];  	struct extended_attribute *ea;  	struct extended_attribute *ea_end = fnode_end_ea(fnode);  	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))  		if (!strcmp(ea->name, key)) { -			if (ea->indirect) +			if (ea_indirect(ea))  				goto indirect; -			if (ea->valuelen >= size) +			if (ea_valuelen(ea) >= size)  				return -EINVAL; -			memcpy(buf, ea_data(ea), ea->valuelen); -			buf[ea->valuelen] = 0; +			memcpy(buf, ea_data(ea), ea_valuelen(ea)); +			buf[ea_valuelen(ea)] = 0;  			return 0;  		} -	a = fnode->ea_secno; -	len = fnode->ea_size_l; -	ano = fnode->ea_anode; +	a = le32_to_cpu(fnode->ea_secno); +	len = le32_to_cpu(fnode->ea_size_l); +	ano = fnode_in_anode(fnode);  	pos = 0;  	while (pos < len) { -		char ex[4 + 255 + 1 + 8];  		ea = (struct extended_attribute *)ex;  		if (pos + 4 > len) {  			hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", @@ -101,25 +101,25 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,  			return -EIO;  		}  		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO; -		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) +		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))  			return -EIO;  		if (!strcmp(ea->name, key)) { -			if (ea->indirect) +			if (ea_indirect(ea))  				goto indirect; -			if (ea->valuelen >= size) +			if (ea_valuelen(ea) >= size)  				return -EINVAL; -			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf)) +			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf))  				return -EIO; -			buf[ea->valuelen] = 0; +			buf[ea_valuelen(ea)] = 0;  			return 0;  		} -		pos += ea->namelen + ea->valuelen + 5; +		pos += ea->namelen + ea_valuelen(ea) + 5;  	}  	return -ENOENT;  indirect:  	if (ea_len(ea) >= size)  		return -EINVAL; -	if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf)) +	if (hpfs_ea_read(s, ea_sec(ea), ea_in_anode(ea), 0, ea_len(ea), buf))  		return -EIO;  	buf[ea_len(ea)] = 0;  	return 0; @@ -136,19 +136,19 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si  	struct extended_attribute *ea_end = fnode_end_ea(fnode);  	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))  		if (!strcmp(ea->name, key)) { -			if (ea->indirect) -				return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); -			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) { -				printk("HPFS: out of memory for EA\n"); +			if (ea_indirect(ea)) +				return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); +			if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { +				pr_err("out of memory for EA\n");  				return NULL;  			} -			memcpy(ret, ea_data(ea), ea->valuelen); -			ret[ea->valuelen] = 0; +			memcpy(ret, ea_data(ea), ea_valuelen(ea)); +			ret[ea_valuelen(ea)] = 0;  			return ret;  		} -	a = fnode->ea_secno; -	len = fnode->ea_size_l; -	ano = fnode->ea_anode; +	a = le32_to_cpu(fnode->ea_secno); +	len = le32_to_cpu(fnode->ea_size_l); +	ano = fnode_in_anode(fnode);  	pos = 0;  	while (pos < len) {  		char ex[4 + 255 + 1 + 8]; @@ -159,23 +159,23 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si  			return NULL;  		}  		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL; -		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) +		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))  			return NULL;  		if (!strcmp(ea->name, key)) { -			if (ea->indirect) -				return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); -			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) { -				printk("HPFS: out of memory for EA\n"); +			if (ea_indirect(ea)) +				return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); +			if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { +				pr_err("out of memory for EA\n");  				return NULL;  			} -			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, ret)) { +			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) {  				kfree(ret);  				return NULL;  			} -			ret[ea->valuelen] = 0; +			ret[ea_valuelen(ea)] = 0;  			return ret;  		} -		pos += ea->namelen + ea->valuelen + 5; +		pos += ea->namelen + ea_valuelen(ea) + 5;  	}  	return NULL;  } @@ -199,17 +199,17 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,  	struct extended_attribute *ea_end = fnode_end_ea(fnode);  	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))  		if (!strcmp(ea->name, key)) { -			if (ea->indirect) { +			if (ea_indirect(ea)) {  				if (ea_len(ea) == size) -					set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); -			} else if (ea->valuelen == size) { +					set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size); +			} else if (ea_valuelen(ea) == size) {  				memcpy(ea_data(ea), data, size);  			}  			return;  		} -	a = fnode->ea_secno; -	len = fnode->ea_size_l; -	ano = fnode->ea_anode; +	a = le32_to_cpu(fnode->ea_secno); +	len = le32_to_cpu(fnode->ea_size_l); +	ano = fnode_in_anode(fnode);  	pos = 0;  	while (pos < len) {  		char ex[4 + 255 + 1 + 8]; @@ -220,76 +220,78 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,  			return;  		}  		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; -		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) +		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))  			return;  		if (!strcmp(ea->name, key)) { -			if (ea->indirect) { +			if (ea_indirect(ea)) {  				if (ea_len(ea) == size) -					set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); +					set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);  			}  			else { -				if (ea->valuelen == size) +				if (ea_valuelen(ea) == size)  					hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);  			}  			return;  		} -		pos += ea->namelen + ea->valuelen + 5; +		pos += ea->namelen + ea_valuelen(ea) + 5;  	} -	if (!fnode->ea_offs) { -		/*if (fnode->ea_size_s) { +	if (!le16_to_cpu(fnode->ea_offs)) { +		/*if (le16_to_cpu(fnode->ea_size_s)) {  			hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0", -				inode->i_ino, fnode->ea_size_s); +				inode->i_ino, le16_to_cpu(fnode->ea_size_s));  			return;  		}*/ -		fnode->ea_offs = 0xc4; +		fnode->ea_offs = cpu_to_le16(0xc4);  	} -	if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) { +	if (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, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",  			(unsigned long)inode->i_ino, -			fnode->ea_offs, fnode->ea_size_s); +			le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));  		return;  	} -	if ((fnode->ea_size_s || !fnode->ea_size_l) && -	     fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) { +	if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) && +	     le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5 <= 0x200) {  		ea = fnode_end_ea(fnode);  		*(char *)ea = 0;  		ea->namelen = strlen(key); -		ea->valuelen = size; +		ea->valuelen_lo = size; +		ea->valuelen_hi = size >> 8;  		strcpy(ea->name, key);  		memcpy(ea_data(ea), data, size); -		fnode->ea_size_s += strlen(key) + size + 5; +		fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5);  		goto ret;  	}  	/* Most the code here is 99.9993422% unused. I hope there are no bugs.  	   But what .. HPFS.IFS has also bugs in ea management. */ -	if (fnode->ea_size_s && !fnode->ea_size_l) { +	if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) {  		secno n;  		struct buffer_head *bh;  		char *data; -		if (!(n = hpfs_alloc_sector(s, fno, 1, 0, 1))) return; +		if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return;  		if (!(data = hpfs_get_sector(s, n, &bh))) {  			hpfs_free_sectors(s, n, 1);  			return;  		} -		memcpy(data, fnode_ea(fnode), fnode->ea_size_s); -		fnode->ea_size_l = fnode->ea_size_s; -		fnode->ea_size_s = 0; -		fnode->ea_secno = n; -		fnode->ea_anode = 0; +		memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s)); +		fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s)); +		fnode->ea_size_s = cpu_to_le16(0); +		fnode->ea_secno = cpu_to_le32(n); +		fnode->flags &= ~FNODE_anode;  		mark_buffer_dirty(bh);  		brelse(bh);  	} -	pos = fnode->ea_size_l + 5 + strlen(key) + size; -	len = (fnode->ea_size_l + 511) >> 9; +	pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size; +	len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9;  	if (pos >= 30000) goto bail;  	while (((pos + 511) >> 9) > len) {  		if (!len) { -			if (!(fnode->ea_secno = hpfs_alloc_sector(s, fno, 1, 0, 1))) -				goto bail; -			fnode->ea_anode = 0; +			secno q = hpfs_alloc_sector(s, fno, 1, 0); +			if (!q) goto bail; +			fnode->ea_secno = cpu_to_le32(q); +			fnode->flags &= ~FNODE_anode;  			len++; -		} else if (!fnode->ea_anode) { -			if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) { +		} else if (!fnode_in_anode(fnode)) { +			if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {  				len++;  			} else {  				/* Aargh... don't know how to create ea anodes :-( */ @@ -298,26 +300,26 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,  				anode_secno a_s;  				if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))  					goto bail; -				anode->up = fno; +				anode->up = cpu_to_le32(fno);  				anode->btree.fnode_parent = 1;  				anode->btree.n_free_nodes--;  				anode->btree.n_used_nodes++; -				anode->btree.first_free += 12; -				anode->u.external[0].disk_secno = fnode->ea_secno; -				anode->u.external[0].file_secno = 0; -				anode->u.external[0].length = len; +				anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12); +				anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno)); +				anode->u.external[0].file_secno = cpu_to_le32(0); +				anode->u.external[0].length = cpu_to_le32(len);  				mark_buffer_dirty(bh);  				brelse(bh); -				fnode->ea_anode = 1; -				fnode->ea_secno = a_s;*/ +				fnode->flags |= FNODE_anode; +				fnode->ea_secno = cpu_to_le32(a_s);*/  				secno new_sec;  				int i; -				if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9), 1))) +				if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9))))  					goto bail;  				for (i = 0; i < len; i++) {  					struct buffer_head *bh1, *bh2;  					void *b1, *b2; -					if (!(b1 = hpfs_map_sector(s, fnode->ea_secno + i, &bh1, len - i - 1))) { +					if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) {  						hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);  						goto bail;  					} @@ -331,13 +333,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,  					mark_buffer_dirty(bh2);  					brelse(bh2);  				} -				hpfs_free_sectors(s, fnode->ea_secno, len); -				fnode->ea_secno = new_sec; +				hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len); +				fnode->ea_secno = cpu_to_le32(new_sec);  				len = (pos + 511) >> 9;  			}  		} -		if (fnode->ea_anode) { -			if (hpfs_add_sector_to_btree(s, fnode->ea_secno, +		if (fnode_in_anode(fnode)) { +			if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),  						     0, len) != -1) {  				len++;  			} else { @@ -349,17 +351,17 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,  	h[1] = strlen(key);  	h[2] = size & 0xff;  	h[3] = size >> 8; -	if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l, 4, h)) goto bail; -	if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 4, h[1] + 1, key)) goto bail; -	if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 5 + h[1], size, data)) goto bail; -	fnode->ea_size_l = pos; +	if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail; +	if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail; +	if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail; +	fnode->ea_size_l = cpu_to_le32(pos);  	ret:  	hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;  	return;  	bail: -	if (fnode->ea_secno) -		if (fnode->ea_anode) hpfs_truncate_btree(s, fnode->ea_secno, 1, (fnode->ea_size_l + 511) >> 9); -		else hpfs_free_sectors(s, fnode->ea_secno + ((fnode->ea_size_l + 511) >> 9), len - ((fnode->ea_size_l + 511) >> 9)); -	else fnode->ea_secno = fnode->ea_size_l = 0; +	if (le32_to_cpu(fnode->ea_secno)) +		if (fnode_in_anode(fnode)) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9); +		else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9)); +	else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0);  } diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index c0340887c7e..7f54e5f76ce 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -6,23 +6,28 @@   *  file VFS functions   */ -#include <linux/smp_lock.h>  #include "hpfs_fn.h" +#include <linux/mpage.h>  #define BLOCKS(size) (((size) + 511) >> 9)  static int hpfs_file_release(struct inode *inode, struct file *file)  { -	lock_kernel(); +	hpfs_lock(inode->i_sb);  	hpfs_write_if_changed(inode); -	unlock_kernel(); +	hpfs_unlock(inode->i_sb);  	return 0;  } -int hpfs_file_fsync(struct file *file, int datasync) +int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)  { -	/*return file_fsync(file, datasync);*/ -	return 0; /* Don't fsync :-) */ +	struct inode *inode = file->f_mapping->host; +	int ret; + +	ret = filemap_write_and_wait_range(file->f_mapping, start, end); +	if (ret) +		return ret; +	return sync_blockdev(inode->i_sb->s_bdev);  }  /* @@ -30,7 +35,7 @@ int hpfs_file_fsync(struct file *file, int datasync)   * so we must ignore such errors.   */ -static secno hpfs_bmap(struct inode *inode, unsigned file_secno) +static secno hpfs_bmap(struct inode *inode, unsigned file_secno, unsigned *n_secs)  {  	struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);  	unsigned n, disk_secno; @@ -38,59 +43,106 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)  	struct buffer_head *bh;  	if (BLOCKS(hpfs_i(inode)->mmu_private) <= file_secno) return 0;  	n = file_secno - hpfs_inode->i_file_sec; -	if (n < hpfs_inode->i_n_secs) return hpfs_inode->i_disk_sec + n; +	if (n < hpfs_inode->i_n_secs) { +		*n_secs = hpfs_inode->i_n_secs - n; +		return hpfs_inode->i_disk_sec + n; +	}  	if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0;  	disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh);  	if (disk_secno == -1) return 0;  	if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0; +	n = file_secno - hpfs_inode->i_file_sec; +	if (n < hpfs_inode->i_n_secs) { +		*n_secs = hpfs_inode->i_n_secs - n; +		return hpfs_inode->i_disk_sec + n; +	} +	*n_secs = 1;  	return disk_secno;  } -static void hpfs_truncate(struct inode *i) +void hpfs_truncate(struct inode *i)  {  	if (IS_IMMUTABLE(i)) return /*-EPERM*/; -	lock_kernel(); +	hpfs_lock_assert(i->i_sb); +  	hpfs_i(i)->i_n_secs = 0;  	i->i_blocks = 1 + ((i->i_size + 511) >> 9);  	hpfs_i(i)->mmu_private = i->i_size;  	hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));  	hpfs_write_inode(i);  	hpfs_i(i)->i_n_secs = 0; -	unlock_kernel();  }  static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)  { +	int r;  	secno s; -	s = hpfs_bmap(inode, iblock); +	unsigned n_secs; +	hpfs_lock(inode->i_sb); +	s = hpfs_bmap(inode, iblock, &n_secs);  	if (s) { +		if (bh_result->b_size >> 9 < n_secs) +			n_secs = bh_result->b_size >> 9;  		map_bh(bh_result, inode->i_sb, s); -		return 0; +		bh_result->b_size = n_secs << 9; +		goto ret_0;  	} -	if (!create) return 0; +	if (!create) goto ret_0;  	if (iblock<<9 != hpfs_i(inode)->mmu_private) {  		BUG(); -		return -EIO; +		r = -EIO; +		goto ret_r;  	}  	if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {  		hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); -		return -ENOSPC; +		r = -ENOSPC; +		goto ret_r;  	}  	inode->i_blocks++;  	hpfs_i(inode)->mmu_private += 512;  	set_buffer_new(bh_result);  	map_bh(bh_result, inode->i_sb, s); -	return 0; +	ret_0: +	r = 0; +	ret_r: +	hpfs_unlock(inode->i_sb); +	return r; +} + +static int hpfs_readpage(struct file *file, struct page *page) +{ +	return mpage_readpage(page, hpfs_get_block);  }  static int hpfs_writepage(struct page *page, struct writeback_control *wbc)  { -	return block_write_full_page(page,hpfs_get_block, wbc); +	return block_write_full_page(page, hpfs_get_block, wbc);  } -static int hpfs_readpage(struct file *file, struct page *page) +static int hpfs_readpages(struct file *file, struct address_space *mapping, +			  struct list_head *pages, unsigned nr_pages)  { -	return block_read_full_page(page,hpfs_get_block); +	return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block); +} + +static int hpfs_writepages(struct address_space *mapping, +			   struct writeback_control *wbc) +{ +	return mpage_writepages(mapping, wbc, hpfs_get_block); +} + +static void hpfs_write_failed(struct address_space *mapping, loff_t to) +{ +	struct inode *inode = mapping->host; + +	hpfs_lock(inode->i_sb); + +	if (to > inode->i_size) { +		truncate_pagecache(inode, inode->i_size); +		hpfs_truncate(inode); +	} + +	hpfs_unlock(inode->i_sb);  }  static int hpfs_write_begin(struct file *file, struct address_space *mapping, @@ -103,15 +155,30 @@ static int hpfs_write_begin(struct file *file, struct address_space *mapping,  	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,  				hpfs_get_block,  				&hpfs_i(mapping->host)->mmu_private); -	if (unlikely(ret)) { -		loff_t isize = mapping->host->i_size; -		if (pos + len > isize) -			vmtruncate(mapping->host, isize); -	} +	if (unlikely(ret)) +		hpfs_write_failed(mapping, pos + len);  	return ret;  } +static int hpfs_write_end(struct file *file, struct address_space *mapping, +			loff_t pos, unsigned len, unsigned copied, +			struct page *pagep, void *fsdata) +{ +	struct inode *inode = mapping->host; +	int err; +	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); +	if (err < len) +		hpfs_write_failed(mapping, pos + len); +	if (!(err < 0)) { +		/* make sure we write it on close, if not earlier */ +		hpfs_lock(inode->i_sb); +		hpfs_i(inode)->i_dirty = 1; +		hpfs_unlock(inode->i_sb); +	} +	return err; +} +  static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)  {  	return generic_block_bmap(mapping,block,hpfs_get_block); @@ -120,30 +187,20 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)  const struct address_space_operations hpfs_aops = {  	.readpage = hpfs_readpage,  	.writepage = hpfs_writepage, -	.sync_page = block_sync_page, +	.readpages = hpfs_readpages, +	.writepages = hpfs_writepages,  	.write_begin = hpfs_write_begin, -	.write_end = generic_write_end, +	.write_end = hpfs_write_end,  	.bmap = _hpfs_bmap  }; -static ssize_t hpfs_file_write(struct file *file, const char __user *buf, -			size_t count, loff_t *ppos) -{ -	ssize_t retval; - -	retval = do_sync_write(file, buf, count, ppos); -	if (retval > 0) -		hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; -	return retval; -} -  const struct file_operations hpfs_file_ops =  {  	.llseek		= generic_file_llseek, -	.read		= do_sync_read, -	.aio_read	= generic_file_aio_read, -	.write		= hpfs_file_write, -	.aio_write	= generic_file_aio_write, +	.read		= new_sync_read, +	.read_iter	= generic_file_read_iter, +	.write		= new_sync_write, +	.write_iter	= generic_file_write_iter,  	.mmap		= generic_file_mmap,  	.release	= hpfs_file_release,  	.fsync		= hpfs_file_fsync, @@ -152,6 +209,5 @@ const struct file_operations hpfs_file_ops =  const struct inode_operations hpfs_file_iops =  { -	.truncate	= hpfs_truncate,  	.setattr	= hpfs_setattr,  }; diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h index 0e84c73cd9c..cce025aff1b 100644 --- a/fs/hpfs/hpfs.h +++ b/fs/hpfs/hpfs.h @@ -19,9 +19,13 @@     For definitive information on HPFS, ask somebody else -- this is guesswork.     There are certain to be many mistakes. */ +#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) +#error unknown endian +#endif +  /* Notation */ -typedef unsigned secno;			/* sector number, partition relative */ +typedef u32 secno;			/* sector number, partition relative */  typedef secno dnode_secno;		/* sector number of a dnode */  typedef secno fnode_secno;		/* sector number of an fnode */ @@ -38,28 +42,28 @@ typedef u32 time32_t;		/* 32-bit time_t type */  struct hpfs_boot_block  { -  unsigned char jmp[3]; -  unsigned char oem_id[8]; -  unsigned char bytes_per_sector[2];	/* 512 */ -  unsigned char sectors_per_cluster; -  unsigned char n_reserved_sectors[2]; -  unsigned char n_fats; -  unsigned char n_rootdir_entries[2]; -  unsigned char n_sectors_s[2]; -  unsigned char media_byte; -  unsigned short sectors_per_fat; -  unsigned short sectors_per_track; -  unsigned short heads_per_cyl; -  unsigned int n_hidden_sectors; -  unsigned int n_sectors_l;		/* size of partition */ -  unsigned char drive_number; -  unsigned char mbz; -  unsigned char sig_28h;		/* 28h */ -  unsigned char vol_serno[4]; -  unsigned char vol_label[11]; -  unsigned char sig_hpfs[8];		/* "HPFS    " */ -  unsigned char pad[448]; -  unsigned short magic;			/* aa55 */ +  u8 jmp[3]; +  u8 oem_id[8]; +  u8 bytes_per_sector[2];	/* 512 */ +  u8 sectors_per_cluster; +  u8 n_reserved_sectors[2]; +  u8 n_fats; +  u8 n_rootdir_entries[2]; +  u8 n_sectors_s[2]; +  u8 media_byte; +  __le16 sectors_per_fat; +  __le16 sectors_per_track; +  __le16 heads_per_cyl; +  __le32 n_hidden_sectors; +  __le32 n_sectors_l;		/* size of partition */ +  u8 drive_number; +  u8 mbz; +  u8 sig_28h;			/* 28h */ +  u8 vol_serno[4]; +  u8 vol_label[11]; +  u8 sig_hpfs[8];		/* "HPFS    " */ +  u8 pad[448]; +  __le16 magic;			/* aa55 */  }; @@ -71,31 +75,29 @@ struct hpfs_boot_block  struct hpfs_super_block  { -  unsigned magic;			/* f995 e849 */ -  unsigned magic1;			/* fa53 e9c5, more magic? */ -  /*unsigned huh202;*/			/* ?? 202 = N. of B. in 1.00390625 S.*/ -  char version;				/* version of a filesystem  usually 2 */ -  char funcversion;			/* functional version - oldest version +  __le32 magic;				/* f995 e849 */ +  __le32 magic1;			/* fa53 e9c5, more magic? */ +  u8 version;				/* version of a filesystem  usually 2 */ +  u8 funcversion;			/* functional version - oldest version    					   of filesystem that can understand  					   this disk */ -  unsigned short int zero;		/* 0 */ -  fnode_secno root;			/* fnode of root directory */ -  secno n_sectors;			/* size of filesystem */ -  unsigned n_badblocks;			/* number of bad blocks */ -  secno bitmaps;			/* pointers to free space bit maps */ -  unsigned zero1;			/* 0 */ -  secno badblocks;			/* bad block list */ -  unsigned zero3;			/* 0 */ -  time32_t last_chkdsk;			/* date last checked, 0 if never */ -  /*unsigned zero4;*/			/* 0 */ -  time32_t last_optimize;			/* date last optimized, 0 if never */ -  secno n_dir_band;			/* number of sectors in dir band */ -  secno dir_band_start;			/* first sector in dir band */ -  secno dir_band_end;			/* last sector in dir band */ -  secno dir_band_bitmap;		/* free space map, 1 dnode per bit */ -  char volume_name[32];			/* not used */ -  secno user_id_table;			/* 8 preallocated sectors - user id */ -  unsigned zero6[103];			/* 0 */ +  __le16 zero;				/* 0 */ +  __le32 root;				/* fnode of root directory */ +  __le32 n_sectors;			/* size of filesystem */ +  __le32 n_badblocks;			/* number of bad blocks */ +  __le32 bitmaps;			/* pointers to free space bit maps */ +  __le32 zero1;				/* 0 */ +  __le32 badblocks;			/* bad block list */ +  __le32 zero3;				/* 0 */ +  __le32 last_chkdsk;			/* date last checked, 0 if never */ +  __le32 last_optimize;			/* date last optimized, 0 if never */ +  __le32 n_dir_band;			/* number of sectors in dir band */ +  __le32 dir_band_start;			/* first sector in dir band */ +  __le32 dir_band_end;			/* last sector in dir band */ +  __le32 dir_band_bitmap;		/* free space map, 1 dnode per bit */ +  u8 volume_name[32];			/* not used */ +  __le32 user_id_table;			/* 8 preallocated sectors - user id */ +  u32 zero6[103];			/* 0 */  }; @@ -107,44 +109,65 @@ struct hpfs_super_block  struct hpfs_spare_block  { -  unsigned magic;			/* f991 1849 */ -  unsigned magic1;			/* fa52 29c5, more magic? */ - -  unsigned dirty: 1;			/* 0 clean, 1 "improperly stopped" */ -  /*unsigned flag1234: 4;*/		/* unknown flags */ -  unsigned sparedir_used: 1;		/* spare dirblks used */ -  unsigned hotfixes_used: 1;		/* hotfixes used */ -  unsigned bad_sector: 1;		/* bad sector, corrupted disk (???) */ -  unsigned bad_bitmap: 1;		/* bad bitmap */ -  unsigned fast: 1;			/* partition was fast formatted */ -  unsigned old_wrote: 1;		/* old version wrote to partion */ -  unsigned old_wrote_1: 1;		/* old version wrote to partion (?) */ -  unsigned install_dasd_limits: 1;	/* HPFS386 flags */ -  unsigned resynch_dasd_limits: 1; -  unsigned dasd_limits_operational: 1; -  unsigned multimedia_active: 1; -  unsigned dce_acls_active: 1; -  unsigned dasd_limits_dirty: 1; -  unsigned flag67: 2; -  unsigned char mm_contlgulty; -  unsigned char unused; - -  secno hotfix_map;			/* info about remapped bad sectors */ -  unsigned n_spares_used;		/* number of hotfixes */ -  unsigned n_spares;			/* number of spares in hotfix map */ -  unsigned n_dnode_spares_free;		/* spare dnodes unused */ -  unsigned n_dnode_spares;		/* length of spare_dnodes[] list, +  __le32 magic;				/* f991 1849 */ +  __le32 magic1;				/* fa52 29c5, more magic? */ + +#ifdef __LITTLE_ENDIAN +  u8 dirty: 1;				/* 0 clean, 1 "improperly stopped" */ +  u8 sparedir_used: 1;			/* spare dirblks used */ +  u8 hotfixes_used: 1;			/* hotfixes used */ +  u8 bad_sector: 1;			/* bad sector, corrupted disk (???) */ +  u8 bad_bitmap: 1;			/* bad bitmap */ +  u8 fast: 1;				/* partition was fast formatted */ +  u8 old_wrote: 1;			/* old version wrote to partion */ +  u8 old_wrote_1: 1;			/* old version wrote to partion (?) */ +#else +  u8 old_wrote_1: 1;			/* old version wrote to partion (?) */ +  u8 old_wrote: 1;			/* old version wrote to partion */ +  u8 fast: 1;				/* partition was fast formatted */ +  u8 bad_bitmap: 1;			/* bad bitmap */ +  u8 bad_sector: 1;			/* bad sector, corrupted disk (???) */ +  u8 hotfixes_used: 1;			/* hotfixes used */ +  u8 sparedir_used: 1;			/* spare dirblks used */ +  u8 dirty: 1;				/* 0 clean, 1 "improperly stopped" */ +#endif + +#ifdef __LITTLE_ENDIAN +  u8 install_dasd_limits: 1;		/* HPFS386 flags */ +  u8 resynch_dasd_limits: 1; +  u8 dasd_limits_operational: 1; +  u8 multimedia_active: 1; +  u8 dce_acls_active: 1; +  u8 dasd_limits_dirty: 1; +  u8 flag67: 2; +#else +  u8 flag67: 2; +  u8 dasd_limits_dirty: 1; +  u8 dce_acls_active: 1; +  u8 multimedia_active: 1; +  u8 dasd_limits_operational: 1; +  u8 resynch_dasd_limits: 1; +  u8 install_dasd_limits: 1;		/* HPFS386 flags */ +#endif + +  u8 mm_contlgulty; +  u8 unused; + +  __le32 hotfix_map;			/* info about remapped bad sectors */ +  __le32 n_spares_used;			/* number of hotfixes */ +  __le32 n_spares;			/* number of spares in hotfix map */ +  __le32 n_dnode_spares_free;		/* spare dnodes unused */ +  __le32 n_dnode_spares;		/* length of spare_dnodes[] list,  					   follows in this block*/ -  secno code_page_dir;			/* code page directory block */ -  unsigned n_code_pages;		/* number of code pages */ -  /*unsigned large_numbers[2];*/	/* ?? */ -  unsigned super_crc;			/* on HPFS386 and LAN Server this is +  __le32 code_page_dir;			/* code page directory block */ +  __le32 n_code_pages;			/* number of code pages */ +  __le32 super_crc;			/* on HPFS386 and LAN Server this is    					   checksum of superblock, on normal  					   OS/2 unused */ -  unsigned spare_crc;			/* on HPFS386 checksum of spareblock */ -  unsigned zero1[15];			/* unused */ -  dnode_secno spare_dnodes[100];	/* emergency free dnode list */ -  unsigned zero2[1];			/* room for more? */ +  __le32 spare_crc;			/* on HPFS386 checksum of spareblock */ +  __le32 zero1[15];			/* unused */ +  __le32 spare_dnodes[100];		/* emergency free dnode list */ +  __le32 zero2[1];			/* room for more? */  };  /* The bad block list is 4 sectors long.  The first word must be zero, @@ -179,18 +202,18 @@ struct hpfs_spare_block  struct code_page_directory  { -  unsigned magic;			/* 4945 21f7 */ -  unsigned n_code_pages;		/* number of pointers following */ -  unsigned zero1[2]; +  __le32 magic;				/* 4945 21f7 */ +  __le32 n_code_pages;			/* number of pointers following */ +  __le32 zero1[2];    struct { -    unsigned short ix;			/* index */ -    unsigned short code_page_number;	/* code page number */ -    unsigned bounds;			/* matches corresponding word +    __le16 ix;				/* index */ +    __le16 code_page_number;		/* code page number */ +    __le32 bounds;			/* matches corresponding word  					   in data block */ -    secno code_page_data;		/* sector number of a code_page_data +    __le32 code_page_data;		/* sector number of a code_page_data  					   containing c.p. array */ -    unsigned short index;		/* index in c.p. array in that sector*/ -    unsigned short unknown;		/* some unknown value; usually 0; +    __le16 index;			/* index in c.p. array in that sector*/ +    __le16 unknown;			/* some unknown value; usually 0;      					   2 in Japanese version */    } array[31];				/* unknown length */  }; @@ -201,21 +224,21 @@ struct code_page_directory  struct code_page_data  { -  unsigned magic;			/* 8945 21f7 */ -  unsigned n_used;			/* # elements used in c_p_data[] */ -  unsigned bounds[3];			/* looks a bit like +  __le32 magic;				/* 8945 21f7 */ +  __le32 n_used;			/* # elements used in c_p_data[] */ +  __le32 bounds[3];			/* looks a bit like  					     (beg1,end1), (beg2,end2)  					   one byte each */ -  unsigned short offs[3];		/* offsets from start of sector +  __le16 offs[3];			/* offsets from start of sector  					   to start of c_p_data[ix] */    struct { -    unsigned short ix;			/* index */ -    unsigned short code_page_number;	/* code page number */ -    unsigned short unknown;		/* the same as in cp directory */ -    unsigned char map[128];		/* upcase table for chars 80..ff */ -    unsigned short zero2; +    __le16 ix;				/* index */ +    __le16 code_page_number;		/* code page number */ +    __le16 unknown;			/* the same as in cp directory */ +    u8 map[128];			/* upcase table for chars 80..ff */ +    __le16 zero2;    } code_page[3]; -  unsigned char incognita[78]; +  u8 incognita[78];  }; @@ -255,50 +278,84 @@ struct code_page_data  #define DNODE_MAGIC   0x77e40aae  struct dnode { -  unsigned magic;			/* 77e4 0aae */ -  unsigned first_free;			/* offset from start of dnode to +  __le32 magic;				/* 77e4 0aae */ +  __le32 first_free;			/* offset from start of dnode to  					   first free dir entry */ -  unsigned root_dnode:1;		/* Is it root dnode? */ -  unsigned increment_me:31;		/* some kind of activity counter? -					   Neither HPFS.IFS nor CHKDSK cares +#ifdef __LITTLE_ENDIAN +  u8 root_dnode: 1;			/* Is it root dnode? */ +  u8 increment_me: 7;			/* some kind of activity counter? */ +					/* Neither HPFS.IFS nor CHKDSK cares +					   if you change this word */ +#else +  u8 increment_me: 7;			/* some kind of activity counter? */ +					/* Neither HPFS.IFS nor CHKDSK cares  					   if you change this word */ -  secno up;				/* (root dnode) directory's fnode +  u8 root_dnode: 1;			/* Is it root dnode? */ +#endif +  u8 increment_me2[3]; +  __le32 up;				/* (root dnode) directory's fnode  					   (nonroot) parent dnode */ -  dnode_secno self;			/* pointer to this dnode */ -  unsigned char dirent[2028];		/* one or more dirents */ +  __le32 self;			/* pointer to this dnode */ +  u8 dirent[2028];			/* one or more dirents */  };  struct hpfs_dirent { -  unsigned short length;		/* offset to next dirent */ -  unsigned first: 1;			/* set on phony ^A^A (".") entry */ -  unsigned has_acl: 1; -  unsigned down: 1;			/* down pointer present (after name) */ -  unsigned last: 1;			/* set on phony \377 entry */ -  unsigned has_ea: 1;			/* entry has EA */ -  unsigned has_xtd_perm: 1;		/* has extended perm list (???) */ -  unsigned has_explicit_acl: 1; -  unsigned has_needea: 1;		/* ?? some EA has NEEDEA set +  __le16 length;			/* offset to next dirent */ + +#ifdef __LITTLE_ENDIAN +  u8 first: 1;				/* set on phony ^A^A (".") entry */ +  u8 has_acl: 1; +  u8 down: 1;				/* down pointer present (after name) */ +  u8 last: 1;				/* set on phony \377 entry */ +  u8 has_ea: 1;				/* entry has EA */ +  u8 has_xtd_perm: 1;			/* has extended perm list (???) */ +  u8 has_explicit_acl: 1; +  u8 has_needea: 1;			/* ?? some EA has NEEDEA set  					   I have no idea why this is  					   interesting in a dir entry */ -  unsigned read_only: 1;		/* dos attrib */ -  unsigned hidden: 1;			/* dos attrib */ -  unsigned system: 1;			/* dos attrib */ -  unsigned flag11: 1;			/* would be volume label dos attrib */ -  unsigned directory: 1;		/* dos attrib */ -  unsigned archive: 1;			/* dos attrib */ -  unsigned not_8x3: 1;			/* name is not 8.3 */ -  unsigned flag15: 1; -  fnode_secno fnode;			/* fnode giving allocation info */ -  time32_t write_date;			/* mtime */ -  unsigned file_size;			/* file length, bytes */ -  time32_t read_date;			/* atime */ -  time32_t creation_date;			/* ctime */ -  unsigned ea_size;			/* total EA length, bytes */ -  unsigned char no_of_acls : 3;		/* number of ACL's */ -  unsigned char reserver : 5; -  unsigned char ix;			/* code page index (of filename), see +#else +  u8 has_needea: 1;			/* ?? some EA has NEEDEA set +					   I have no idea why this is +					   interesting in a dir entry */ +  u8 has_explicit_acl: 1; +  u8 has_xtd_perm: 1;			/* has extended perm list (???) */ +  u8 has_ea: 1;				/* entry has EA */ +  u8 last: 1;				/* set on phony \377 entry */ +  u8 down: 1;				/* down pointer present (after name) */ +  u8 has_acl: 1; +  u8 first: 1;				/* set on phony ^A^A (".") entry */ +#endif + +#ifdef __LITTLE_ENDIAN +  u8 read_only: 1;			/* dos attrib */ +  u8 hidden: 1;				/* dos attrib */ +  u8 system: 1;				/* dos attrib */ +  u8 flag11: 1;				/* would be volume label dos attrib */ +  u8 directory: 1;			/* dos attrib */ +  u8 archive: 1;			/* dos attrib */ +  u8 not_8x3: 1;			/* name is not 8.3 */ +  u8 flag15: 1; +#else +  u8 flag15: 1; +  u8 not_8x3: 1;			/* name is not 8.3 */ +  u8 archive: 1;			/* dos attrib */ +  u8 directory: 1;			/* dos attrib */ +  u8 flag11: 1;				/* would be volume label dos attrib */ +  u8 system: 1;				/* dos attrib */ +  u8 hidden: 1;				/* dos attrib */ +  u8 read_only: 1;			/* dos attrib */ +#endif + +  __le32 fnode;				/* fnode giving allocation info */ +  __le32 write_date;			/* mtime */ +  __le32 file_size;			/* file length, bytes */ +  __le32 read_date;			/* atime */ +  __le32 creation_date;			/* ctime */ +  __le32 ea_size;			/* total EA length, bytes */ +  u8 no_of_acls;			/* number of ACL's (low 3 bits) */ +  u8 ix;				/* code page index (of filename), see  					   struct code_page_data */ -  unsigned char namelen, name[1];	/* file name */ +  u8 namelen, name[1];			/* file name */    /* dnode_secno down;	  btree down pointer, if present,       			  follows name on next word boundary, or maybe it  			  precedes next dirent, which is on a word boundary. */ @@ -318,38 +375,36 @@ struct hpfs_dirent {  struct bplus_leaf_node  { -  unsigned file_secno;			/* first file sector in extent */ -  unsigned 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  { -  unsigned 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  { -  unsigned hbff: 1;	/* high bit of first free entry offset */ -  unsigned flag1: 1; -  unsigned flag2: 1; -  unsigned flag3: 1; -  unsigned flag4: 1; -  unsigned 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 */ -  unsigned binary_search: 1;		/* suggest binary search (unused) */ -  unsigned internal: 1;			/* 1 -> (internal) tree of anodes -					   0 -> (leaf) list of extents */ -  unsigned char fill[3]; -  unsigned char n_free_nodes;		/* free nodes in following array */ -  unsigned char n_used_nodes;		/* used nodes in following array */ -  unsigned short first_free;		/* offset from start of header to +					   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 fill[3]; +  u8 n_free_nodes;			/* free nodes in following array */ +  u8 n_used_nodes;			/* used nodes in following array */ +  __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 @@ -359,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 @@ -367,62 +432,56 @@ struct bplus_header  #define FNODE_MAGIC 0xf7e40aae +enum {FNODE_anode = cpu_to_le16(2), FNODE_dir = cpu_to_le16(256)};  struct fnode  { -  unsigned magic;			/* f7e4 0aae */ -  unsigned zero1[2];			/* read history */ -  unsigned char len, name[15];		/* true length, truncated name */ -  fnode_secno up;			/* pointer to file's directory fnode */ -  /*unsigned zero2[3];*/ -  secno acl_size_l; -  secno acl_secno; -  unsigned short acl_size_s; -  char acl_anode; -  char zero2;				/* history bit count */ -  unsigned ea_size_l;			/* length of disk-resident ea's */ -  secno ea_secno;			/* first sector of disk-resident ea's*/ -  unsigned short ea_size_s;		/* length of fnode-resident ea's */ - -  unsigned flag0: 1; -  unsigned ea_anode: 1;			/* 1 -> ea_secno is an anode */ -  unsigned flag2: 1; -  unsigned flag3: 1; -  unsigned flag4: 1; -  unsigned flag5: 1; -  unsigned flag6: 1; -  unsigned flag7: 1; -  unsigned dirflag: 1;			/* 1 -> directory.  first & only extent +  __le32 magic;				/* f7e4 0aae */ +  __le32 zero1[2];			/* read history */ +  u8 len, name[15];			/* true length, truncated name */ +  __le32 up;				/* pointer to file's directory fnode */ +  __le32 acl_size_l; +  __le32 acl_secno; +  __le16 acl_size_s; +  u8 acl_anode; +  u8 zero2;				/* history bit count */ +  __le32 ea_size_l;			/* length of disk-resident ea's */ +  __le32 ea_secno;			/* first sector of disk-resident ea's*/ +  __le16 ea_size_s;			/* length of fnode-resident ea's */ + +  __le16 flags;				/* bit 1 set -> ea_secno is an anode */ +					/* bit 8 set -> directory.  first & only extent  					   points to dnode. */ -  unsigned flag9: 1; -  unsigned flag10: 1; -  unsigned flag11: 1; -  unsigned flag12: 1; -  unsigned flag13: 1; -  unsigned flag14: 1; -  unsigned flag15: 1; -    struct bplus_header btree;		/* b+ tree, 8 extents or 12 subtrees */    union {      struct bplus_leaf_node external[8];      struct bplus_internal_node internal[12];    } u; -  unsigned file_size;			/* file length, bytes */ -  unsigned n_needea;			/* number of EA's with NEEDEA set */ -  char user_id[16];			/* unused */ -  unsigned short ea_offs;		/* offset from start of fnode +  __le32 file_size;			/* file length, bytes */ +  __le32 n_needea;			/* number of EA's with NEEDEA set */ +  u8 user_id[16];			/* unused */ +  __le16 ea_offs;			/* offset from start of fnode  					   to first fnode-resident ea */ -  char dasd_limit_treshhold; -  char dasd_limit_delta; -  unsigned dasd_limit; -  unsigned dasd_usage; -  /*unsigned zero5[2];*/ -  unsigned char ea[316];		/* zero or more EA's, packed together +  u8 dasd_limit_treshhold; +  u8 dasd_limit_delta; +  __le32 dasd_limit; +  __le32 dasd_usage; +  u8 ea[316];				/* zero or more EA's, packed together  					   with no alignment padding.  					   (Do not use this name, get here  					   via fnode + ea_offs. I think.) */  }; +static inline bool fnode_in_anode(struct fnode *p) +{ +	return (p->flags & FNODE_anode) != 0; +} + +static inline bool fnode_is_dir(struct fnode *p) +{ +	return (p->flags & FNODE_dir) != 0; +} +  /* anode: 99.44% pure allocation tree */ @@ -430,9 +489,9 @@ struct fnode  struct anode  { -  unsigned magic;			/* 37e4 0aae */ -  anode_secno self;			/* pointer to this anode */ -  secno up;				/* parent anode or fnode */ +  __le32 magic;				/* 37e4 0aae */ +  __le32 self;				/* pointer to this anode */ +  __le32 up;				/* parent anode or fnode */    struct bplus_header btree;		/* b+tree, 40 extents or 60 subtrees */    union { @@ -440,7 +499,7 @@ struct anode      struct bplus_internal_node internal[60];    } u; -  unsigned fill[3];			/* unused */ +  __le32 fill[3];			/* unused */  }; @@ -459,33 +518,40 @@ struct anode     run, or in multiple runs.  Flags in the fnode tell whether the EA list     is immediate, in a single run, or in multiple runs. */ +enum {EA_indirect = 1, EA_anode = 2, EA_needea = 128 };  struct extended_attribute  { -  unsigned indirect: 1;			/* 1 -> value gives sector number +  u8 flags;				/* bit 0 set -> value gives sector number  					   where real value starts */ -  unsigned anode: 1;			/* 1 -> sector is an anode +					/* bit 1 set -> sector is an anode  					   that points to fragmented value */ -  unsigned flag2: 1; -  unsigned flag3: 1; -  unsigned flag4: 1; -  unsigned flag5: 1; -  unsigned flag6: 1; -  unsigned needea: 1;			/* required ea */ -  unsigned char namelen;		/* length of name, bytes */ -  unsigned short valuelen;		/* length of value, bytes */ -  unsigned char name[0]; +					/* bit 7 set -> required ea */ +  u8 namelen;				/* length of name, bytes */ +  u8 valuelen_lo;			/* length of value, bytes */ +  u8 valuelen_hi;			/* length of value, bytes */ +  u8 name[];    /* -    unsigned char name[namelen];	ascii attrib name -    unsigned char nul;			terminating '\0', not counted -    unsigned char value[valuelen];	value, arbitrary -      if this.indirect, valuelen is 8 and the value is -        unsigned length;		real length of value, bytes +    u8 name[namelen];			ascii attrib name +    u8 nul;				terminating '\0', not counted +    u8 value[valuelen];			value, arbitrary +      if this.flags & 1, valuelen is 8 and the value is +        u32 length;			real length of value, bytes          secno secno;			sector address where it starts        if this.anode, the above sector number is the root of an anode tree          which points to the value.    */  }; +static inline bool ea_indirect(struct extended_attribute *ea) +{ +	return ea->flags & EA_indirect; +} + +static inline bool ea_in_anode(struct extended_attribute *ea) +{ +	return ea->flags & EA_anode; +} +  /*     Local Variables:     comment-column: 40 diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 2fee17d0d9a..b63b75fa00e 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -8,11 +8,17 @@  //#define DBG  //#define DEBUG_LOCKS +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/mutex.h>  #include <linux/pagemap.h>  #include <linux/buffer_head.h>  #include <linux/slab.h> +#include <asm/unaligned.h>  #include "hpfs.h" @@ -26,21 +32,15 @@  #define ALLOC_FWD_MAX	128  #define ALLOC_M		1  #define FNODE_RD_AHEAD	16 -#define ANODE_RD_AHEAD	16 -#define DNODE_RD_AHEAD	4 +#define ANODE_RD_AHEAD	0 +#define DNODE_RD_AHEAD	72 +#define COUNT_RD_AHEAD	62  #define FREE_DNODES_ADD	58  #define FREE_DNODES_DEL	29  #define CHKCOND(x,y) if (!(x)) printk y -#ifdef DBG -#define PRINTK(x) printk x -#else -#undef PRINTK -#define PRINTK(x) -#endif -  struct hpfs_inode_info {  	loff_t mmu_private;  	ino_t i_parent_dir;	/* (directories) gives fnode of parent dir */ @@ -51,18 +51,16 @@ struct hpfs_inode_info {  	unsigned i_disk_sec;	/* (files) minimalist cache of alloc info */  	unsigned i_n_secs;	/* (files) minimalist cache of alloc info */  	unsigned i_ea_size;	/* size of extended attributes */ -	unsigned i_conv : 2;	/* (files) crlf->newline hackery */  	unsigned i_ea_mode : 1;	/* file's permission is stored in ea */  	unsigned i_ea_uid : 1;	/* file's uid is stored in ea */  	unsigned i_ea_gid : 1;	/* file's gid is stored in ea */  	unsigned i_dirty : 1; -	struct mutex i_mutex; -	struct mutex i_parent_mutex;  	loff_t **i_rddir_off;  	struct inode vfs_inode;  };  struct hpfs_sb_info { +	struct mutex hpfs_mutex;	/* global hpfs lock */  	ino_t sb_root;			/* inode number of root dir */  	unsigned sb_fs_size;		/* file system size, sectors */  	unsigned sb_bitmaps;		/* sector number of bitmap list */ @@ -71,10 +69,9 @@ struct hpfs_sb_info {  	unsigned sb_dmap;		/* sector number of dnode bit map */  	unsigned sb_n_free;		/* free blocks for statfs, or -1 */  	unsigned sb_n_free_dnodes;	/* free dnodes for statfs, or -1 */ -	uid_t sb_uid;			/* uid from mount options */ -	gid_t sb_gid;			/* gid from mount options */ +	kuid_t sb_uid;			/* uid from mount options */ +	kgid_t sb_gid;			/* gid from mount options */  	umode_t sb_mode;		/* mode from mount options */ -	unsigned sb_conv : 2;		/* crlf->newline hackery */  	unsigned sb_eas : 2;		/* eas: 0-ignore, 1-ro, 2-rw */  	unsigned sb_err : 2;		/* on errs: 0-cont, 1-ro, 2-panic */  	unsigned sb_chk : 2;		/* checks: 0-no, 1-normal, 2-strict */ @@ -84,23 +81,13 @@ struct hpfs_sb_info {  	unsigned char *sb_cp_table;	/* code page tables: */  					/* 	128 bytes uppercasing table & */  					/*	128 bytes lowercasing table */ -	unsigned *sb_bmp_dir;		/* main bitmap directory */ +	__le32 *sb_bmp_dir;		/* main bitmap directory */  	unsigned sb_c_bitmap;		/* current bitmap */  	unsigned sb_max_fwd_alloc;	/* max forwad allocation */ -	struct mutex hpfs_creation_de;	/* when creating dirents, nobody else -					   can alloc blocks */ -	/*unsigned sb_mounting : 1;*/  	int sb_timeshift; +	struct rcu_head rcu;  }; -/* - * conv= options - */ - -#define CONV_BINARY 0			/* no conversion */ -#define CONV_TEXT 1			/* crlf->newline */ -#define CONV_AUTO 2			/* decide based on file contents */ -  /* Four 512-byte buffers and the 2k block obtained by concatenating them */  struct quad_buffer_head { @@ -113,7 +100,7 @@ struct quad_buffer_head {  static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)  {    CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n")); -  return *(dnode_secno *) ((void *) de + de->length - 4); +  return le32_to_cpu(*(__le32 *) ((void *) de + le16_to_cpu(de->length) - 4));  }  /* The first dir entry in a dnode */ @@ -127,41 +114,46 @@ static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)  static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)  { -  CHKCOND(dnode->first_free>=0x14 && dnode->first_free<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %d\n",(int)dnode->first_free)); -  return (void *) dnode + dnode->first_free; +  CHKCOND(le32_to_cpu(dnode->first_free)>=0x14 && le32_to_cpu(dnode->first_free)<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %x\n",(unsigned)le32_to_cpu(dnode->first_free))); +  return (void *) dnode + le32_to_cpu(dnode->first_free);  }  /* The dir entry after dir entry de */  static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)  { -  CHKCOND(de->length>=0x20 && de->length<0x800,("HPFS: de_next_de: de->length = %d\n",(int)de->length)); -  return (void *) de + de->length; +  CHKCOND(le16_to_cpu(de->length)>=0x20 && le16_to_cpu(de->length)<0x800,("HPFS: de_next_de: de->length = %x\n",(unsigned)le16_to_cpu(de->length))); +  return (void *) de + le16_to_cpu(de->length);  }  static inline struct extended_attribute *fnode_ea(struct fnode *fnode)  { -	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s); +	return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s));  }  static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)  { -	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s); +	return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s)); +} + +static unsigned ea_valuelen(struct extended_attribute *ea) +{ +	return ea->valuelen_lo + 256 * ea->valuelen_hi;  }  static inline struct extended_attribute *next_ea(struct extended_attribute *ea)  { -	return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea->valuelen); +	return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea_valuelen(ea));  }  static inline secno ea_sec(struct extended_attribute *ea)  { -	return *(secno *)((char *)ea + 9 + ea->namelen); +	return le32_to_cpu(get_unaligned((__le32 *)((char *)ea + 9 + ea->namelen)));  }  static inline secno ea_len(struct extended_attribute *ea)  { -	return *(secno *)((char *)ea + 5 + ea->namelen); +	return le32_to_cpu(get_unaligned((__le32 *)((char *)ea + 5 + ea->namelen)));  }  static inline char *ea_data(struct extended_attribute *ea) @@ -186,13 +178,13 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)  	dst->not_8x3 = n;  } -static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n) +static inline unsigned tstbits(__le32 *bmp, unsigned b, unsigned n)  {  	int i;  	if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n; -	if (!((bmp[(b & 0x3fff) >> 5] >> (b & 0x1f)) & 1)) return 1; +	if (!((le32_to_cpu(bmp[(b & 0x3fff) >> 5]) >> (b & 0x1f)) & 1)) return 1;  	for (i = 1; i < n; i++) -		if (/*b+i < 0x4000 &&*/ !((bmp[((b+i) & 0x3fff) >> 5] >> ((b+i) & 0x1f)) & 1)) +		if (!((le32_to_cpu(bmp[((b+i) & 0x3fff) >> 5]) >> ((b+i) & 0x1f)) & 1))  			return i + 1;  	return 0;  } @@ -200,12 +192,12 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)  /* alloc.c */  int hpfs_chk_sectors(struct super_block *, secno, int, char *); -secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int, int); +secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int);  int hpfs_alloc_if_possible(struct super_block *, secno);  void hpfs_free_sectors(struct super_block *, secno, unsigned);  int hpfs_check_free_dnodes(struct super_block *, int);  void hpfs_free_dnode(struct super_block *, secno); -struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *, int); +struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *);  struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **);  struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); @@ -222,8 +214,7 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);  /* buffer.c */ -void hpfs_lock_creation(struct super_block *); -void hpfs_unlock_creation(struct super_block *); +void hpfs_prefetch_sectors(struct super_block *, unsigned, int);  void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);  void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);  void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int); @@ -233,11 +224,11 @@ void hpfs_mark_4buffers_dirty(struct quad_buffer_head *);  /* dentry.c */ -void hpfs_set_dentry_operations(struct dentry *); +extern const struct dentry_operations hpfs_dentry_operations;  /* dir.c */ -struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); +struct dentry *hpfs_lookup(struct inode *, struct dentry *, unsigned int);  extern const struct file_operations hpfs_dir_ops;  /* dnode.c */ @@ -247,7 +238,7 @@ void hpfs_del_pos(struct inode *, loff_t *);  struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,  				const unsigned char *, unsigned, secno);  int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned, -		    struct hpfs_dirent *, int); +		    struct hpfs_dirent *);  int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);  void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);  dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno); @@ -268,7 +259,8 @@ void hpfs_set_ea(struct inode *, struct fnode *, const char *,  /* file.c */ -int hpfs_file_fsync(struct file *, int); +int hpfs_file_fsync(struct file *, loff_t, loff_t, int); +void hpfs_truncate(struct inode *);  extern const struct file_operations hpfs_file_ops;  extern const struct inode_operations hpfs_file_iops;  extern const struct address_space_operations hpfs_aops; @@ -285,10 +277,11 @@ void hpfs_evict_inode(struct inode *);  /* map.c */ -unsigned *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *); -unsigned *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *); +__le32 *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *); +__le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *); +void hpfs_prefetch_bitmap(struct super_block *, unsigned);  unsigned char *hpfs_load_code_page(struct super_block *, secno); -secno *hpfs_load_bitmap_directory(struct super_block *, secno bmp); +__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp);  struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);  struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **);  struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *); @@ -303,7 +296,6 @@ int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned,  		       const unsigned char *, unsigned, int);  int hpfs_is_name_long(const unsigned char *, unsigned);  void hpfs_adjust_length(const unsigned char *, unsigned *); -void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned);  /* namei.c */ @@ -322,10 +314,10 @@ static inline struct hpfs_sb_info *hpfs_sb(struct super_block *sb)  /* super.c */ -void hpfs_error(struct super_block *, const char *, ...) -	__attribute__((format (printf, 2, 3))); +__printf(2, 3) +void hpfs_error(struct super_block *, const char *, ...);  int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *); -unsigned hpfs_count_one_bitmap(struct super_block *, secno); +unsigned hpfs_get_free_dnodes(struct super_block *);  /*   * local time (HPFS) to GMT (Unix) @@ -342,3 +334,30 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t)  	extern struct timezone sys_tz;  	return t - sys_tz.tz_minuteswest * 60 - hpfs_sb(s)->sb_timeshift;  } + +/* + * Locking: + * + * hpfs_lock() locks the whole filesystem. It must be taken + * on any method called by the VFS. + * + * We don't do any per-file locking anymore, it is hard to + * review and HPFS is not performance-sensitive anyway. + */ +static inline void hpfs_lock(struct super_block *s) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	mutex_lock(&sbi->hpfs_mutex); +} + +static inline void hpfs_unlock(struct super_block *s) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	mutex_unlock(&sbi->hpfs_mutex); +} + +static inline void hpfs_lock_assert(struct super_block *s) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	WARN_ON(!mutex_is_locked(&sbi->hpfs_mutex)); +} diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 56f0da1cfd1..7ce4b74234a 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -6,8 +6,8 @@   *  inode VFS functions   */ -#include <linux/smp_lock.h>  #include <linux/slab.h> +#include <linux/user_namespace.h>  #include "hpfs_fn.h"  void hpfs_init_inode(struct inode *i) @@ -18,7 +18,6 @@ void hpfs_init_inode(struct inode *i)  	i->i_uid = hpfs_sb(sb)->sb_uid;  	i->i_gid = hpfs_sb(sb)->sb_gid;  	i->i_mode = hpfs_sb(sb)->sb_mode; -	hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;  	i->i_size = -1;  	i->i_blocks = -1; @@ -55,21 +54,21 @@ void hpfs_read_inode(struct inode *i)  		i->i_mode &= ~0111;  		i->i_op = &hpfs_file_iops;  		i->i_fop = &hpfs_file_ops; -		i->i_nlink = 0;*/ +		clear_nlink(i);*/  		make_bad_inode(i);  		return;  	}  	if (hpfs_sb(i->i_sb)->sb_eas) {  		if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) {  			if (ea_size == 2) { -				i->i_uid = le16_to_cpu(*(__le16*)ea); +				i_uid_write(i, le16_to_cpu(*(__le16*)ea));  				hpfs_inode->i_ea_uid = 1;  			}  			kfree(ea);  		}  		if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) {  			if (ea_size == 2) { -				i->i_gid = le16_to_cpu(*(__le16*)ea); +				i_gid_write(i, le16_to_cpu(*(__le16*)ea));  				hpfs_inode->i_ea_gid = 1;  			}  			kfree(ea); @@ -79,7 +78,7 @@ void hpfs_read_inode(struct inode *i)  			i->i_mode = S_IFLNK | 0777;  			i->i_op = &page_symlink_inode_operations;  			i->i_data.a_ops = &hpfs_symlink_aops; -			i->i_nlink = 1; +			set_nlink(i, 1);  			i->i_size = ea_size;  			i->i_blocks = 1;  			brelse(bh); @@ -103,7 +102,7 @@ void hpfs_read_inode(struct inode *i)  			}  			if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {  				brelse(bh); -				i->i_nlink = 1; +				set_nlink(i, 1);  				i->i_size = 0;  				i->i_blocks = 1;  				init_special_inode(i, mode, @@ -112,13 +111,13 @@ void hpfs_read_inode(struct inode *i)  			}  		}  	} -	if (fnode->dirflag) { +	if (fnode_is_dir(fnode)) {  		int n_dnodes, n_subdirs;  		i->i_mode |= S_IFDIR;  		i->i_op = &hpfs_dir_iops;  		i->i_fop = &hpfs_dir_ops; -		hpfs_inode->i_parent_dir = fnode->up; -		hpfs_inode->i_dno = fnode->u.external[0].disk_secno; +		hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up); +		hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno);  		if (hpfs_sb(sb)->sb_chk >= 2) {  			struct buffer_head *bh0;  			if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0); @@ -127,14 +126,14 @@ void hpfs_read_inode(struct inode *i)  		hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL);  		i->i_blocks = 4 * n_dnodes;  		i->i_size = 2048 * n_dnodes; -		i->i_nlink = 2 + n_subdirs; +		set_nlink(i, 2 + n_subdirs);  	} else {  		i->i_mode |= S_IFREG;  		if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111;  		i->i_op = &hpfs_file_iops;  		i->i_fop = &hpfs_file_ops; -		i->i_nlink = 1; -		i->i_size = fnode->file_size; +		set_nlink(i, 1); +		i->i_size = le32_to_cpu(fnode->file_size);  		i->i_blocks = ((i->i_size + 511) >> 9) + 1;  		i->i_data.a_ops = &hpfs_aops;  		hpfs_i(i)->mmu_private = i->i_size; @@ -145,19 +144,19 @@ void hpfs_read_inode(struct inode *i)  static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)  {  	struct hpfs_inode_info *hpfs_inode = hpfs_i(i); -	/*if (fnode->acl_size_l || fnode->acl_size_s) { +	/*if (le32_to_cpu(fnode->acl_size_l) || le16_to_cpu(fnode->acl_size_s)) {  		   Some unknown structures like ACL may be in fnode,  		   we'd better not overwrite them -		hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); +		hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 structures", i->i_ino);  	} else*/ if (hpfs_sb(i->i_sb)->sb_eas >= 2) {  		__le32 ea; -		if ((i->i_uid != hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) { -			ea = cpu_to_le32(i->i_uid); +		if (!uid_eq(i->i_uid, hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) { +			ea = cpu_to_le32(i_uid_read(i));  			hpfs_set_ea(i, fnode, "UID", (char*)&ea, 2);  			hpfs_inode->i_ea_uid = 1;  		} -		if ((i->i_gid != hpfs_sb(i->i_sb)->sb_gid) || hpfs_inode->i_ea_gid) { -			ea = cpu_to_le32(i->i_gid); +		if (!gid_eq(i->i_gid, hpfs_sb(i->i_sb)->sb_gid) || hpfs_inode->i_ea_gid) { +			ea = cpu_to_le32(i_gid_read(i));  			hpfs_set_ea(i, fnode, "GID", (char *)&ea, 2);  			hpfs_inode->i_ea_gid = 1;  		} @@ -184,13 +183,12 @@ void hpfs_write_inode(struct inode *i)  	struct inode *parent;  	if (i->i_ino == hpfs_sb(i->i_sb)->sb_root) return;  	if (hpfs_inode->i_rddir_off && !atomic_read(&i->i_count)) { -		if (*hpfs_inode->i_rddir_off) printk("HPFS: write_inode: some position still there\n"); +		if (*hpfs_inode->i_rddir_off) +			pr_err("write_inode: some position still there\n");  		kfree(hpfs_inode->i_rddir_off);  		hpfs_inode->i_rddir_off = NULL;  	} -	mutex_lock(&hpfs_inode->i_parent_mutex);  	if (!i->i_nlink) { -		mutex_unlock(&hpfs_inode->i_parent_mutex);  		return;  	}  	parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir); @@ -201,14 +199,9 @@ void hpfs_write_inode(struct inode *i)  			hpfs_read_inode(parent);  			unlock_new_inode(parent);  		} -		mutex_lock(&hpfs_inode->i_mutex);  		hpfs_write_inode_nolock(i); -		mutex_unlock(&hpfs_inode->i_mutex);  		iput(parent); -	} else { -		mark_inode_dirty(i);  	} -	mutex_unlock(&hpfs_inode->i_parent_mutex);  }  void hpfs_write_inode_nolock(struct inode *i) @@ -227,30 +220,30 @@ void hpfs_write_inode_nolock(struct inode *i)  		}  	} else de = NULL;  	if (S_ISREG(i->i_mode)) { -		fnode->file_size = i->i_size; -		if (de) de->file_size = i->i_size; +		fnode->file_size = cpu_to_le32(i->i_size); +		if (de) de->file_size = cpu_to_le32(i->i_size);  	} else if (S_ISDIR(i->i_mode)) { -		fnode->file_size = 0; -		if (de) de->file_size = 0; +		fnode->file_size = cpu_to_le32(0); +		if (de) de->file_size = cpu_to_le32(0);  	}  	hpfs_write_inode_ea(i, fnode);  	if (de) { -		de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec); -		de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec); -		de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec); +		de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec)); +		de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec)); +		de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));  		de->read_only = !(i->i_mode & 0222); -		de->ea_size = hpfs_inode->i_ea_size; +		de->ea_size = cpu_to_le32(hpfs_inode->i_ea_size);  		hpfs_mark_4buffers_dirty(&qbh);  		hpfs_brelse4(&qbh);  	}  	if (S_ISDIR(i->i_mode)) {  		if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) { -			de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec); -			de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec); -			de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec); +			de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec)); +			de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec)); +			de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));  			de->read_only = !(i->i_mode & 0222); -			de->ea_size = /*hpfs_inode->i_ea_size*/0; -			de->file_size = 0; +			de->ea_size = cpu_to_le32(/*hpfs_inode->i_ea_size*/0); +			de->file_size = cpu_to_le32(0);  			hpfs_mark_4buffers_dirty(&qbh);  			hpfs_brelse4(&qbh);  		} else @@ -267,9 +260,15 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)  	struct inode *inode = dentry->d_inode;  	int error = -EINVAL; -	lock_kernel(); +	hpfs_lock(inode->i_sb);  	if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root)  		goto out_unlock; +	if ((attr->ia_valid & ATTR_UID) && +	    from_kuid(&init_user_ns, attr->ia_uid) >= 0x10000) +		goto out_unlock; +	if ((attr->ia_valid & ATTR_GID) && +	    from_kgid(&init_user_ns, attr->ia_gid) >= 0x10000) +		goto out_unlock;  	if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)  		goto out_unlock; @@ -279,18 +278,20 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)  	if ((attr->ia_valid & ATTR_SIZE) &&  	    attr->ia_size != i_size_read(inode)) { -		error = vmtruncate(inode, attr->ia_size); +		error = inode_newsize_ok(inode, attr->ia_size);  		if (error) -			return error; +			goto out_unlock; + +		truncate_setsize(inode, attr->ia_size); +		hpfs_truncate(inode);  	}  	setattr_copy(inode, attr); -	mark_inode_dirty(inode);  	hpfs_write_inode(inode);   out_unlock: -	unlock_kernel(); +	hpfs_unlock(inode->i_sb);  	return error;  } @@ -304,11 +305,11 @@ void hpfs_write_if_changed(struct inode *inode)  void hpfs_evict_inode(struct inode *inode)  { -	truncate_inode_pages(&inode->i_data, 0); -	end_writeback(inode); +	truncate_inode_pages_final(&inode->i_data); +	clear_inode(inode);  	if (!inode->i_nlink) { -		lock_kernel(); +		hpfs_lock(inode->i_sb);  		hpfs_remove_fnode(inode->i_sb, inode->i_ino); -		unlock_kernel(); +		hpfs_unlock(inode->i_sb);  	}  } 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;  } diff --git a/fs/hpfs/name.c b/fs/hpfs/name.c index f24736d7a43..b00d396d22c 100644 --- a/fs/hpfs/name.c +++ b/fs/hpfs/name.c @@ -8,39 +8,6 @@  #include "hpfs_fn.h" -static const char *text_postfix[]={ -".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF", -".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS", -".RC", ".TEX", ".TXT", ".Y", ""}; - -static const char *text_prefix[]={ -"AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ", -"MAKEFILE", "READ.ME", "README", "TERMCAP", ""}; - -void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len) -{ -	struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); -	int i; -	if (hpfs_inode->i_conv != CONV_AUTO) return; -	for (i = 0; *text_postfix[i]; i++) { -		int l = strlen(text_postfix[i]); -		if (l <= len) -			if (!hpfs_compare_names(inode->i_sb, text_postfix[i], l, name + len - l, l, 0)) -				goto text; -	} -	for (i = 0; *text_prefix[i]; i++) { -		int l = strlen(text_prefix[i]); -		if (l <= len) -			if (!hpfs_compare_names(inode->i_sb, text_prefix[i], l, name, l, 0)) -				goto text; -	} -	hpfs_inode->i_conv = CONV_BINARY; -	return; -	text: -	hpfs_inode->i_conv = CONV_TEXT; -	return; -} -  static inline int not_allowed_char(unsigned char c)  {  	return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' || @@ -89,14 +56,15 @@ unsigned char *hpfs_translate_name(struct super_block *s, unsigned char *from,  	unsigned char *to;  	int i;  	if (hpfs_sb(s)->sb_chk >= 2) if (hpfs_is_name_long(from, len) != lng) { -		printk("HPFS: Long name flag mismatch - name "); -		for (i=0; i<len; i++) printk("%c", from[i]); -		printk(" misidentified as %s.\n", lng ? "short" : "long"); -		printk("HPFS: It's nothing serious. It could happen because of bug in OS/2.\nHPFS: Set checks=normal to disable this message.\n"); +		pr_err("Long name flag mismatch - name "); +		for (i = 0; i < len; i++) +			pr_cont("%c", from[i]); +		pr_cont(" misidentified as %s.\n", lng ? "short" : "long"); +		pr_err("It's nothing serious. It could happen because of bug in OS/2.\nSet checks=normal to disable this message.\n");  	}  	if (!lc) return from;  	if (!(to = kmalloc(len, GFP_KERNEL))) { -		printk("HPFS: can't allocate memory for name conversion buffer\n"); +		pr_err("can't allocate memory for name conversion buffer\n");  		return from;  	}  	for (i = 0; i < len; i++) to[i] = locase(hpfs_sb(s)->sb_cp_table,from[i]); diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 11c2b4080f6..bdbc2c3080a 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -6,10 +6,9 @@   *  adding & removing files & directories   */  #include <linux/sched.h> -#include <linux/smp_lock.h>  #include "hpfs_fn.h" -static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)  {  	const unsigned char *name = dentry->d_name.name;  	unsigned len = dentry->d_name.len; @@ -25,12 +24,12 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	struct hpfs_dirent dee;  	int err;  	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err; -	lock_kernel(); +	hpfs_lock(dir->i_sb);  	err = -ENOSPC;  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);  	if (!fnode)  		goto bail; -	dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0, 1); +	dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);  	if (!dnode)  		goto bail1;  	memset(&dee, 0, sizeof dee); @@ -38,8 +37,8 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	if (!(mode & 0222)) dee.read_only = 1;  	/*dee.archive = 0;*/  	dee.hidden = name[0] == '.'; -	dee.fnode = fno; -	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); +	dee.fnode = cpu_to_le32(fno); +	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));  	result = new_inode(dir->i_sb);  	if (!result)  		goto bail2; @@ -47,7 +46,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	result->i_ino = fno;  	hpfs_i(result)->i_parent_dir = dir->i_ino;  	hpfs_i(result)->i_dno = dno; -	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); +	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));  	result->i_ctime.tv_nsec = 0;   	result->i_mtime.tv_nsec = 0;   	result->i_atime.tv_nsec = 0;  @@ -57,12 +56,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	result->i_fop = &hpfs_dir_ops;  	result->i_blocks = 4;  	result->i_size = 2048; -	result->i_nlink = 2; +	set_nlink(result, 2);  	if (dee.read_only)  		result->i_mode &= ~0222; -	mutex_lock(&hpfs_i(dir)->i_mutex); -	r = hpfs_add_dirent(dir, name, len, &dee, 0); +	r = hpfs_add_dirent(dir, name, len, &dee);  	if (r == 1)  		goto bail3;  	if (r == -1) { @@ -71,21 +69,21 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	}  	fnode->len = len;  	memcpy(fnode->name, name, len > 15 ? 15 : len); -	fnode->up = dir->i_ino; -	fnode->dirflag = 1; +	fnode->up = cpu_to_le32(dir->i_ino); +	fnode->flags |= FNODE_dir;  	fnode->btree.n_free_nodes = 7;  	fnode->btree.n_used_nodes = 1; -	fnode->btree.first_free = 0x14; -	fnode->u.external[0].disk_secno = dno; -	fnode->u.external[0].file_secno = -1; +	fnode->btree.first_free = cpu_to_le16(0x14); +	fnode->u.external[0].disk_secno = cpu_to_le32(dno); +	fnode->u.external[0].file_secno = cpu_to_le32(-1);  	dnode->root_dnode = 1; -	dnode->up = fno; +	dnode->up = cpu_to_le32(fno);  	de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0); -	de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, get_seconds()); +	de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));  	if (!(mode & 0222)) de->read_only = 1;  	de->first = de->directory = 1;  	/*de->hidden = de->system = 0;*/ -	de->fnode = fno; +	de->fnode = cpu_to_le32(fno);  	mark_buffer_dirty(bh);  	brelse(bh);  	hpfs_mark_4buffers_dirty(&qbh0); @@ -93,8 +91,8 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	inc_nlink(dir);  	insert_inode_hash(result); -	if (result->i_uid != current_fsuid() || -	    result->i_gid != current_fsgid() || +	if (!uid_eq(result->i_uid, current_fsuid()) || +	    !gid_eq(result->i_gid, current_fsgid()) ||  	    result->i_mode != (mode | S_IFDIR)) {  		result->i_uid = current_fsuid();  		result->i_gid = current_fsgid(); @@ -102,11 +100,9 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  		hpfs_write_inode_nolock(result);  	}  	d_instantiate(dentry, result); -	mutex_unlock(&hpfs_i(dir)->i_mutex); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return 0;  bail3: -	mutex_unlock(&hpfs_i(dir)->i_mutex);  	iput(result);  bail2:  	hpfs_brelse4(&qbh0); @@ -115,11 +111,11 @@ bail1:  	brelse(bh);  	hpfs_free_sectors(dir->i_sb, fno, 1);  bail: -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return err;  } -static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) +static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)  {  	const unsigned char *name = dentry->d_name.name;  	unsigned len = dentry->d_name.len; @@ -132,7 +128,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc  	int err;  	if ((err = hpfs_chk_name(name, &len)))  		return err==-ENOENT ? -EINVAL : err; -	lock_kernel(); +	hpfs_lock(dir->i_sb);  	err = -ENOSPC;  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);  	if (!fnode) @@ -141,8 +137,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc  	if (!(mode & 0222)) dee.read_only = 1;  	dee.archive = 1;  	dee.hidden = name[0] == '.'; -	dee.fnode = fno; -	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); +	dee.fnode = cpu_to_le32(fno); +	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));  	result = new_inode(dir->i_sb);  	if (!result) @@ -154,10 +150,9 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc  	result->i_mode &= ~0111;  	result->i_op = &hpfs_file_iops;  	result->i_fop = &hpfs_file_ops; -	result->i_nlink = 1; -	hpfs_decide_conv(result, name, len); +	set_nlink(result, 1);  	hpfs_i(result)->i_parent_dir = dir->i_ino; -	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); +	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));  	result->i_ctime.tv_nsec = 0;  	result->i_mtime.tv_nsec = 0;  	result->i_atime.tv_nsec = 0; @@ -169,8 +164,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc  	result->i_data.a_ops = &hpfs_aops;  	hpfs_i(result)->mmu_private = 0; -	mutex_lock(&hpfs_i(dir)->i_mutex); -	r = hpfs_add_dirent(dir, name, len, &dee, 0); +	r = hpfs_add_dirent(dir, name, len, &dee);  	if (r == 1)  		goto bail2;  	if (r == -1) { @@ -179,14 +173,14 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc  	}  	fnode->len = len;  	memcpy(fnode->name, name, len > 15 ? 15 : len); -	fnode->up = dir->i_ino; +	fnode->up = cpu_to_le32(dir->i_ino);  	mark_buffer_dirty(bh);  	brelse(bh);  	insert_inode_hash(result); -	if (result->i_uid != current_fsuid() || -	    result->i_gid != current_fsgid() || +	if (!uid_eq(result->i_uid, current_fsuid()) || +	    !gid_eq(result->i_gid, current_fsgid()) ||  	    result->i_mode != (mode | S_IFREG)) {  		result->i_uid = current_fsuid();  		result->i_gid = current_fsgid(); @@ -194,22 +188,20 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc  		hpfs_write_inode_nolock(result);  	}  	d_instantiate(dentry, result); -	mutex_unlock(&hpfs_i(dir)->i_mutex); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return 0;  bail2: -	mutex_unlock(&hpfs_i(dir)->i_mutex);  	iput(result);  bail1:  	brelse(bh);  	hpfs_free_sectors(dir->i_sb, fno, 1);  bail: -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return err;  } -static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) +static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)  {  	const unsigned char *name = dentry->d_name.name;  	unsigned len = dentry->d_name.len; @@ -224,7 +216,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t  	if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;  	if (!new_valid_dev(rdev))  		return -EINVAL; -	lock_kernel(); +	hpfs_lock(dir->i_sb);  	err = -ENOSPC;  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);  	if (!fnode) @@ -233,8 +225,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t  	if (!(mode & 0222)) dee.read_only = 1;  	dee.archive = 1;  	dee.hidden = name[0] == '.'; -	dee.fnode = fno; -	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); +	dee.fnode = cpu_to_le32(fno); +	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));  	result = new_inode(dir->i_sb);  	if (!result) @@ -243,20 +235,19 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t  	hpfs_init_inode(result);  	result->i_ino = fno;  	hpfs_i(result)->i_parent_dir = dir->i_ino; -	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); +	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));  	result->i_ctime.tv_nsec = 0;  	result->i_mtime.tv_nsec = 0;  	result->i_atime.tv_nsec = 0;  	hpfs_i(result)->i_ea_size = 0;  	result->i_uid = current_fsuid();  	result->i_gid = current_fsgid(); -	result->i_nlink = 1; +	set_nlink(result, 1);  	result->i_size = 0;  	result->i_blocks = 1;  	init_special_inode(result, mode, rdev); -	mutex_lock(&hpfs_i(dir)->i_mutex); -	r = hpfs_add_dirent(dir, name, len, &dee, 0); +	r = hpfs_add_dirent(dir, name, len, &dee);  	if (r == 1)  		goto bail2;  	if (r == -1) { @@ -265,25 +256,23 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t  	}  	fnode->len = len;  	memcpy(fnode->name, name, len > 15 ? 15 : len); -	fnode->up = dir->i_ino; +	fnode->up = cpu_to_le32(dir->i_ino);  	mark_buffer_dirty(bh);  	insert_inode_hash(result);  	hpfs_write_inode_nolock(result);  	d_instantiate(dentry, result); -	mutex_unlock(&hpfs_i(dir)->i_mutex);  	brelse(bh); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return 0;  bail2: -	mutex_unlock(&hpfs_i(dir)->i_mutex);  	iput(result);  bail1:  	brelse(bh);  	hpfs_free_sectors(dir->i_sb, fno, 1);  bail: -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return err;  } @@ -299,9 +288,9 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy  	struct inode *result;  	int err;  	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err; -	lock_kernel(); +	hpfs_lock(dir->i_sb);  	if (hpfs_sb(dir->i_sb)->sb_eas < 2) { -		unlock_kernel(); +		hpfs_unlock(dir->i_sb);  		return -EPERM;  	}  	err = -ENOSPC; @@ -311,8 +300,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy  	memset(&dee, 0, sizeof dee);  	dee.archive = 1;  	dee.hidden = name[0] == '.'; -	dee.fnode = fno; -	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); +	dee.fnode = cpu_to_le32(fno); +	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));  	result = new_inode(dir->i_sb);  	if (!result) @@ -320,7 +309,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy  	result->i_ino = fno;  	hpfs_init_inode(result);  	hpfs_i(result)->i_parent_dir = dir->i_ino; -	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); +	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));  	result->i_ctime.tv_nsec = 0;  	result->i_mtime.tv_nsec = 0;  	result->i_atime.tv_nsec = 0; @@ -329,13 +318,12 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy  	result->i_uid = current_fsuid();  	result->i_gid = current_fsgid();  	result->i_blocks = 1; -	result->i_nlink = 1; +	set_nlink(result, 1);  	result->i_size = strlen(symlink);  	result->i_op = &page_symlink_inode_operations;  	result->i_data.a_ops = &hpfs_symlink_aops; -	mutex_lock(&hpfs_i(dir)->i_mutex); -	r = hpfs_add_dirent(dir, name, len, &dee, 0); +	r = hpfs_add_dirent(dir, name, len, &dee);  	if (r == 1)  		goto bail2;  	if (r == -1) { @@ -344,7 +332,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy  	}  	fnode->len = len;  	memcpy(fnode->name, name, len > 15 ? 15 : len); -	fnode->up = dir->i_ino; +	fnode->up = cpu_to_le32(dir->i_ino);  	hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));  	mark_buffer_dirty(bh);  	brelse(bh); @@ -353,17 +341,15 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy  	hpfs_write_inode_nolock(result);  	d_instantiate(dentry, result); -	mutex_unlock(&hpfs_i(dir)->i_mutex); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return 0;  bail2: -	mutex_unlock(&hpfs_i(dir)->i_mutex);  	iput(result);  bail1:  	brelse(bh);  	hpfs_free_sectors(dir->i_sb, fno, 1);  bail: -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return err;  } @@ -375,16 +361,13 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)  	struct hpfs_dirent *de;  	struct inode *inode = dentry->d_inode;  	dnode_secno dno; -	fnode_secno fno;  	int r;  	int rep = 0;  	int err; -	lock_kernel(); +	hpfs_lock(dir->i_sb);  	hpfs_adjust_length(name, &len);  again: -	mutex_lock(&hpfs_i(inode)->i_parent_mutex); -	mutex_lock(&hpfs_i(dir)->i_mutex);  	err = -ENOENT;  	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);  	if (!de) @@ -398,7 +381,6 @@ again:  	if (de->directory)  		goto out1; -	fno = de->fnode;  	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);  	switch (r) {  	case 1: @@ -411,31 +393,26 @@ again:  		if (rep++)  			break; -		mutex_unlock(&hpfs_i(dir)->i_mutex); -		mutex_unlock(&hpfs_i(inode)->i_parent_mutex);  		dentry_unhash(dentry);  		if (!d_unhashed(dentry)) { -			dput(dentry); -			unlock_kernel(); +			hpfs_unlock(dir->i_sb);  			return -ENOSPC;  		} -		if (generic_permission(inode, MAY_WRITE, NULL) || +		if (generic_permission(inode, MAY_WRITE) ||  		    !S_ISREG(inode->i_mode) ||  		    get_write_access(inode)) {  			d_rehash(dentry); -			dput(dentry);  		} else {  			struct iattr newattrs; -			/*printk("HPFS: truncating file before delete.\n");*/ +			/*pr_info("truncating file before delete.\n");*/  			newattrs.ia_size = 0;  			newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -			err = notify_change(dentry, &newattrs); +			err = notify_change(dentry, &newattrs, NULL);  			put_write_access(inode); -			dput(dentry);  			if (!err)  				goto again;  		} -		unlock_kernel(); +		hpfs_unlock(dir->i_sb);  		return -ENOSPC;  	default:  		drop_nlink(inode); @@ -446,9 +423,7 @@ again:  out1:  	hpfs_brelse4(&qbh);  out: -	mutex_unlock(&hpfs_i(dir)->i_mutex); -	mutex_unlock(&hpfs_i(inode)->i_parent_mutex); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return err;  } @@ -460,15 +435,12 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)  	struct hpfs_dirent *de;  	struct inode *inode = dentry->d_inode;  	dnode_secno dno; -	fnode_secno fno;  	int n_items = 0;  	int err;  	int r;  	hpfs_adjust_length(name, &len); -	lock_kernel(); -	mutex_lock(&hpfs_i(inode)->i_parent_mutex); -	mutex_lock(&hpfs_i(dir)->i_mutex); +	hpfs_lock(dir->i_sb);  	err = -ENOENT;  	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);  	if (!de) @@ -487,7 +459,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)  	if (n_items)  		goto out1; -	fno = de->fnode;  	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);  	switch (r) {  	case 1: @@ -506,9 +477,7 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)  out1:  	hpfs_brelse4(&qbh);  out: -	mutex_unlock(&hpfs_i(dir)->i_mutex); -	mutex_unlock(&hpfs_i(inode)->i_parent_mutex); -	unlock_kernel(); +	hpfs_unlock(dir->i_sb);  	return err;  } @@ -521,21 +490,21 @@ static int hpfs_symlink_readpage(struct file *file, struct page *page)  	int err;  	err = -EIO; -	lock_kernel(); +	hpfs_lock(i->i_sb);  	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))  		goto fail;  	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);  	brelse(bh);  	if (err)  		goto fail; -	unlock_kernel(); +	hpfs_unlock(i->i_sb);  	SetPageUptodate(page);  	kunmap(page);  	unlock_page(page);  	return 0;  fail: -	unlock_kernel(); +	hpfs_unlock(i->i_sb);  	SetPageError(page);  	kunmap(page);  	unlock_page(page); @@ -563,18 +532,13 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	struct buffer_head *bh;  	struct fnode *fnode;  	int err; +  	if ((err = hpfs_chk_name(new_name, &new_len))) return err;  	err = 0;  	hpfs_adjust_length(old_name, &old_len); -	lock_kernel(); +	hpfs_lock(i->i_sb);  	/* order doesn't matter, due to VFS exclusion */ -	mutex_lock(&hpfs_i(i)->i_parent_mutex); -	if (new_inode) -		mutex_lock(&hpfs_i(new_inode)->i_parent_mutex); -	mutex_lock(&hpfs_i(old_dir)->i_mutex); -	if (new_dir != old_dir) -		mutex_lock(&hpfs_i(new_dir)->i_mutex);  	/* Erm? Moving over the empty non-busy directory is perfectly legal */  	if (new_inode && S_ISDIR(new_inode->i_mode)) { @@ -611,9 +575,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	if (new_dir == old_dir) hpfs_brelse4(&qbh); -	hpfs_lock_creation(i->i_sb); -	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) { -		hpfs_unlock_creation(i->i_sb); +	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) {  		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");  		err = r == 1 ? -ENOSPC : -EFSERROR;  		if (new_dir != old_dir) hpfs_brelse4(&qbh); @@ -622,20 +584,17 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	if (new_dir == old_dir)  		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) { -			hpfs_unlock_creation(i->i_sb);  			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");  			err = -ENOENT;  			goto end1;  		}  	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) { -		hpfs_unlock_creation(i->i_sb);  		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");  		err = r == 2 ? -ENOSPC : -EFSERROR;  		goto end1;  	} -	hpfs_unlock_creation(i->i_sb); -	 +  	end:  	hpfs_i(i)->i_parent_dir = new_dir->i_ino;  	if (S_ISDIR(i->i_mode)) { @@ -643,23 +602,15 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,  		drop_nlink(old_dir);  	}  	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) { -		fnode->up = new_dir->i_ino; +		fnode->up = cpu_to_le32(new_dir->i_ino);  		fnode->len = new_len;  		memcpy(fnode->name, new_name, new_len>15?15:new_len);  		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);  		mark_buffer_dirty(bh);  		brelse(bh);  	} -	hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv; -	hpfs_decide_conv(i, new_name, new_len);  end1: -	if (old_dir != new_dir) -		mutex_unlock(&hpfs_i(new_dir)->i_mutex); -	mutex_unlock(&hpfs_i(old_dir)->i_mutex); -	mutex_unlock(&hpfs_i(i)->i_parent_mutex); -	if (new_inode) -		mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex); -	unlock_kernel(); +	hpfs_unlock(i->i_sb);  	return err;  } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 6c5f01597c3..7cd00d3a7c9 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -13,21 +13,21 @@  #include <linux/statfs.h>  #include <linux/magic.h>  #include <linux/sched.h> -#include <linux/smp_lock.h>  #include <linux/bitmap.h>  #include <linux/slab.h>  /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ -static void mark_dirty(struct super_block *s) +static void mark_dirty(struct super_block *s, int remount)  { -	if (hpfs_sb(s)->sb_chkdsk && !(s->s_flags & MS_RDONLY)) { +	if (hpfs_sb(s)->sb_chkdsk && (remount || !(s->s_flags & MS_RDONLY))) {  		struct buffer_head *bh;  		struct hpfs_spare_block *sb;  		if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {  			sb->dirty = 1;  			sb->old_wrote = 0;  			mark_buffer_dirty(bh); +			sync_dirty_buffer(bh);  			brelse(bh);  		}  	} @@ -41,10 +41,12 @@ static void unmark_dirty(struct super_block *s)  	struct buffer_head *bh;  	struct hpfs_spare_block *sb;  	if (s->s_flags & MS_RDONLY) return; +	sync_blockdev(s->s_bdev);  	if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {  		sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error;  		sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error;  		mark_buffer_dirty(bh); +		sync_dirty_buffer(bh);  		brelse(bh);  	}  } @@ -60,22 +62,26 @@ void hpfs_error(struct super_block *s, const char *fmt, ...)  	vsnprintf(err_buf, sizeof(err_buf), fmt, args);  	va_end(args); -	printk("HPFS: filesystem error: %s", err_buf); +	pr_err("filesystem error: %s", err_buf);  	if (!hpfs_sb(s)->sb_was_error) {  		if (hpfs_sb(s)->sb_err == 2) { -			printk("; crashing the system because you wanted it\n"); -			mark_dirty(s); +			pr_cont("; crashing the system because you wanted it\n"); +			mark_dirty(s, 0);  			panic("HPFS panic");  		} else if (hpfs_sb(s)->sb_err == 1) { -			if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n"); +			if (s->s_flags & MS_RDONLY) +				pr_cont("; already mounted read-only\n");  			else { -				printk("; remounting read-only\n"); -				mark_dirty(s); +				pr_cont("; remounting read-only\n"); +				mark_dirty(s, 0);  				s->s_flags |= MS_RDONLY;  			} -		} else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n"); -		else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n"); -	} else printk("\n"); +		} else if (s->s_flags & MS_RDONLY) +				pr_cont("; going on - but anything won't be destroyed because it's read-only\n"); +		else +			pr_cont("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n"); +	} else +		pr_cont("\n");  	hpfs_sb(s)->sb_was_error = 1;  } @@ -99,30 +105,35 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,  	return 0;  } -static void hpfs_put_super(struct super_block *s) +static void free_sbi(struct hpfs_sb_info *sbi)  { -	struct hpfs_sb_info *sbi = hpfs_sb(s); - -	lock_kernel(); -  	kfree(sbi->sb_cp_table);  	kfree(sbi->sb_bmp_dir); -	unmark_dirty(s); -	s->s_fs_info = NULL;  	kfree(sbi); +} -	unlock_kernel(); +static void lazy_free_sbi(struct rcu_head *rcu) +{ +	free_sbi(container_of(rcu, struct hpfs_sb_info, rcu));  } -unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) +static void hpfs_put_super(struct super_block *s) +{ +	hpfs_lock(s); +	unmark_dirty(s); +	hpfs_unlock(s); +	call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi); +} + +static unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)  {  	struct quad_buffer_head qbh;  	unsigned long *bits;  	unsigned count; -	bits = hpfs_map_4sectors(s, secno, &qbh, 4); +	bits = hpfs_map_4sectors(s, secno, &qbh, 0);  	if (!bits) -		return 0; +		return (unsigned)-1;  	count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);  	hpfs_brelse4(&qbh);  	return count; @@ -133,34 +144,54 @@ static unsigned count_bitmaps(struct super_block *s)  	unsigned n, count, n_bands;  	n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;  	count = 0; -	for (n = 0; n < n_bands; n++) -		count += hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_bmp_dir[n]); +	for (n = 0; n < COUNT_RD_AHEAD; n++) { +		hpfs_prefetch_bitmap(s, n); +	} +	for (n = 0; n < n_bands; n++) { +		unsigned c; +		hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD); +		c = hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n])); +		if (c != (unsigned)-1) +			count += c; +	}  	return count;  } +unsigned hpfs_get_free_dnodes(struct super_block *s) +{ +	struct hpfs_sb_info *sbi = hpfs_sb(s); +	if (sbi->sb_n_free_dnodes == (unsigned)-1) { +		unsigned c = hpfs_count_one_bitmap(s, sbi->sb_dmap); +		if (c == (unsigned)-1) +			return 0; +		sbi->sb_n_free_dnodes = c; +	} +	return sbi->sb_n_free_dnodes; +} +  static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)  {  	struct super_block *s = dentry->d_sb;  	struct hpfs_sb_info *sbi = hpfs_sb(s);  	u64 id = huge_encode_dev(s->s_bdev->bd_dev); -	lock_kernel(); -	/*if (sbi->sb_n_free == -1) {*/ +	hpfs_lock(s); + +	if (sbi->sb_n_free == (unsigned)-1)  		sbi->sb_n_free = count_bitmaps(s); -		sbi->sb_n_free_dnodes = hpfs_count_one_bitmap(s, sbi->sb_dmap); -	/*}*/ +  	buf->f_type = s->s_magic;  	buf->f_bsize = 512;  	buf->f_blocks = sbi->sb_fs_size;  	buf->f_bfree = sbi->sb_n_free;  	buf->f_bavail = sbi->sb_n_free;  	buf->f_files = sbi->sb_dirband_size / 4; -	buf->f_ffree = sbi->sb_n_free_dnodes; +	buf->f_ffree = hpfs_get_free_dnodes(s);  	buf->f_fsid.val[0] = (u32)id;  	buf->f_fsid.val[1] = (u32)(id >> 32);  	buf->f_namelen = 254; -	unlock_kernel(); +	hpfs_unlock(s);  	return 0;  } @@ -177,17 +208,21 @@ static struct inode *hpfs_alloc_inode(struct super_block *sb)  	return &ei->vfs_inode;  } -static void hpfs_destroy_inode(struct inode *inode) +static void hpfs_i_callback(struct rcu_head *head)  { +	struct inode *inode = container_of(head, struct inode, i_rcu);  	kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));  } +static void hpfs_destroy_inode(struct inode *inode) +{ +	call_rcu(&inode->i_rcu, hpfs_i_callback); +} +  static void init_once(void *foo)  {  	struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; -	mutex_init(&ei->i_mutex); -	mutex_init(&ei->i_parent_mutex);  	inode_init_once(&ei->vfs_inode);  } @@ -205,6 +240,11 @@ static int init_inodecache(void)  static void destroy_inodecache(void)  { +	/* +	 * Make sure all delayed rcu free inodes are flushed before we +	 * destroy cache. +	 */ +	rcu_barrier();  	kmem_cache_destroy(hpfs_inode_cachep);  } @@ -216,7 +256,6 @@ static void destroy_inodecache(void)  enum {  	Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis, -	Opt_conv_binary, Opt_conv_text, Opt_conv_auto,  	Opt_check_none, Opt_check_normal, Opt_check_strict,  	Opt_err_cont, Opt_err_ro, Opt_err_panic,  	Opt_eas_no, Opt_eas_ro, Opt_eas_rw, @@ -231,9 +270,6 @@ static const match_table_t tokens = {  	{Opt_umask, "umask=%o"},  	{Opt_case_lower, "case=lower"},  	{Opt_case_asis, "case=asis"}, -	{Opt_conv_binary, "conv=binary"}, -	{Opt_conv_text, "conv=text"}, -	{Opt_conv_auto, "conv=auto"},  	{Opt_check_none, "check=none"},  	{Opt_check_normal, "check=normal"},  	{Opt_check_strict, "check=strict"}, @@ -250,8 +286,8 @@ static const match_table_t tokens = {  	{Opt_err, NULL},  }; -static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask, -		      int *lowercase, int *conv, int *eas, int *chk, int *errs, +static int parse_opts(char *opts, kuid_t *uid, kgid_t *gid, umode_t *umask, +		      int *lowercase, int *eas, int *chk, int *errs,  		      int *chkdsk, int *timeshift)  {  	char *p; @@ -260,7 +296,7 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,  	if (!opts)  		return 1; -	/*printk("Parsing opts: '%s'\n",opts);*/ +	/*pr_info("Parsing opts: '%s'\n",opts);*/  	while ((p = strsep(&opts, ",")) != NULL) {  		substring_t args[MAX_OPT_ARGS]; @@ -275,12 +311,16 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,  		case Opt_uid:  			if (match_int(args, &option))  				return 0; -			*uid = option; +			*uid = make_kuid(current_user_ns(), option); +			if (!uid_valid(*uid)) +				return 0;  			break;  		case Opt_gid:  			if (match_int(args, &option))  				return 0; -			*gid = option; +			*gid = make_kgid(current_user_ns(), option); +			if (!gid_valid(*gid)) +				return 0;  			break;  		case Opt_umask:  			if (match_octal(args, &option)) @@ -293,15 +333,6 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,  		case Opt_case_asis:  			*lowercase = 0;  			break; -		case Opt_conv_binary: -			*conv = CONV_BINARY; -			break; -		case Opt_conv_text: -			*conv = CONV_TEXT; -			break; -		case Opt_conv_auto: -			*conv = CONV_AUTO; -			break;  		case Opt_check_none:  			*chk = 0;  			break; @@ -360,7 +391,7 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,  static inline void hpfs_help(void)  { -	printk("\n\ +	pr_info("\n\  HPFS filesystem options:\n\        help              do not mount and display this text\n\        uid=xxx           set uid of files that don't have uid specified in eas\n\ @@ -368,9 +399,6 @@ HPFS filesystem options:\n\        umask=xxx         set mode of files that don't have mode specified in eas\n\        case=lower        lowercase all files\n\        case=asis         do not lowercase files (default)\n\ -      conv=binary       do not convert CR/LF -> LF (default)\n\ -      conv=auto         convert only files with known text extensions\n\ -      conv=text         convert all files\n\        check=none        no fs checks - kernel may crash on corrupted filesystem\n\        check=normal      do some checks - it should not crash (default)\n\        check=strict      do extra time-consuming checks, used for debugging\n\ @@ -389,27 +417,28 @@ HPFS filesystem options:\n\  static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)  { -	uid_t uid; -	gid_t gid; +	kuid_t uid; +	kgid_t gid;  	umode_t umask; -	int lowercase, conv, eas, chk, errs, chkdsk, timeshift; +	int lowercase, eas, chk, errs, chkdsk, timeshift;  	int o;  	struct hpfs_sb_info *sbi = hpfs_sb(s);  	char *new_opts = kstrdup(data, GFP_KERNEL); +	sync_filesystem(s); +  	*flags |= MS_NOATIME; -	lock_kernel(); -	lock_super(s); +	hpfs_lock(s);  	uid = sbi->sb_uid; gid = sbi->sb_gid;  	umask = 0777 & ~sbi->sb_mode; -	lowercase = sbi->sb_lowercase; conv = sbi->sb_conv; +	lowercase = sbi->sb_lowercase;  	eas = sbi->sb_eas; chk = sbi->sb_chk; chkdsk = sbi->sb_chkdsk;  	errs = sbi->sb_err; timeshift = sbi->sb_timeshift; -	if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase, &conv, +	if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase,  	    &eas, &chk, &errs, &chkdsk, ×hift))) { -		printk("HPFS: bad mount options.\n"); +		pr_err("bad mount options.\n");  		goto out_err;  	}  	if (o == 2) { @@ -417,7 +446,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)  		goto out_err;  	}  	if (timeshift != sbi->sb_timeshift) { -		printk("HPFS: timeshift can't be changed using remount.\n"); +		pr_err("timeshift can't be changed using remount.\n");  		goto out_err;  	} @@ -425,21 +454,19 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)  	sbi->sb_uid = uid; sbi->sb_gid = gid;  	sbi->sb_mode = 0777 & ~umask; -	sbi->sb_lowercase = lowercase; sbi->sb_conv = conv; +	sbi->sb_lowercase = lowercase;  	sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk;  	sbi->sb_err = errs; sbi->sb_timeshift = timeshift; -	if (!(*flags & MS_RDONLY)) mark_dirty(s); +	if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);  	replace_mount_options(s, new_opts); -	unlock_super(s); -	unlock_kernel(); +	hpfs_unlock(s);  	return 0;  out_err: -	unlock_super(s); -	unlock_kernel(); +	hpfs_unlock(s);  	kfree(new_opts);  	return -EINVAL;  } @@ -466,10 +493,10 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	struct hpfs_sb_info *sbi;  	struct inode *root; -	uid_t uid; -	gid_t gid; +	kuid_t uid; +	kgid_t gid;  	umode_t umask; -	int lowercase, conv, eas, chk, errs, chkdsk, timeshift; +	int lowercase, eas, chk, errs, chkdsk, timeshift;  	dnode_secno root_dno;  	struct hpfs_dirent *de = NULL; @@ -477,36 +504,30 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	int o; -	lock_kernel(); -  	save_mount_options(s, options);  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);  	if (!sbi) { -		unlock_kernel();  		return -ENOMEM;  	}  	s->s_fs_info = sbi; -	sbi->sb_bmp_dir = NULL; -	sbi->sb_cp_table = NULL; - -	mutex_init(&sbi->hpfs_creation_de); +	mutex_init(&sbi->hpfs_mutex); +	hpfs_lock(s);  	uid = current_uid();  	gid = current_gid();  	umask = current_umask();  	lowercase = 0; -	conv = CONV_BINARY;  	eas = 2;  	chk = 1;  	errs = 1;  	chkdsk = 1;  	timeshift = 0; -	if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, &conv, +	if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase,  	    &eas, &chk, &errs, &chkdsk, ×hift))) { -		printk("HPFS: bad mount options.\n"); +		pr_err("bad mount options.\n");  		goto bail0;  	}  	if (o==2) { @@ -522,19 +543,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3;  	/* Check magics */ -	if (/*bootblock->magic != BB_MAGIC -	    ||*/ superblock->magic != SB_MAGIC -	    || spareblock->magic != SP_MAGIC) { -		if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n"); +	if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC +	    ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC +	    || le32_to_cpu(spareblock->magic) != SP_MAGIC) { +		if (!silent) +			pr_err("Bad magic ... probably not HPFS\n");  		goto bail4;  	}  	/* Check version */  	if (!(s->s_flags & MS_RDONLY) &&  	      superblock->funcversion != 2 && superblock->funcversion != 3) { -		printk("HPFS: Bad version %d,%d. Mount readonly to go around\n", +		pr_err("Bad version %d,%d. Mount readonly to go around\n",  			(int)superblock->version, (int)superblock->funcversion); -		printk("HPFS: please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - mikulas@artax.karlin.mff.cuni.cz\n"); +		pr_err("please try recent version of HPFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi and if it still can't understand this format, contact author - mikulas@artax.karlin.mff.cuni.cz\n");  		goto bail4;  	} @@ -543,20 +565,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	/* Fill superblock stuff */  	s->s_magic = HPFS_SUPER_MAGIC;  	s->s_op = &hpfs_sops; - -	sbi->sb_root = superblock->root; -	sbi->sb_fs_size = superblock->n_sectors; -	sbi->sb_bitmaps = superblock->bitmaps; -	sbi->sb_dirband_start = superblock->dir_band_start; -	sbi->sb_dirband_size = superblock->n_dir_band; -	sbi->sb_dmap = superblock->dir_band_bitmap; +	s->s_d_op = &hpfs_dentry_operations; + +	sbi->sb_root = le32_to_cpu(superblock->root); +	sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors); +	sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps); +	sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start); +	sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band); +	sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap);  	sbi->sb_uid = uid;  	sbi->sb_gid = gid;  	sbi->sb_mode = 0777 & ~umask;  	sbi->sb_n_free = -1;  	sbi->sb_n_free_dnodes = -1;  	sbi->sb_lowercase = lowercase; -	sbi->sb_conv = conv;  	sbi->sb_eas = eas;  	sbi->sb_chk = chk;  	sbi->sb_chkdsk = chkdsk; @@ -566,15 +588,21 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	sbi->sb_cp_table = NULL;  	sbi->sb_c_bitmap = -1;  	sbi->sb_max_fwd_alloc = 0xffffff; -	 + +	if (sbi->sb_fs_size >= 0x80000000) { +		hpfs_error(s, "invalid size in superblock: %08x", +			(unsigned)sbi->sb_fs_size); +		goto bail4; +	} +  	/* Load bitmap directory */ -	if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps))) +	if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))  		goto bail4;  	/* Check for general fs errors*/  	if (spareblock->dirty && !spareblock->old_wrote) {  		if (errs == 2) { -			printk("HPFS: Improperly stopped, not mounted\n"); +			pr_err("Improperly stopped, not mounted\n");  			goto bail4;  		}  		hpfs_error(s, "improperly stopped"); @@ -588,46 +616,50 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	if (spareblock->hotfixes_used || spareblock->n_spares_used) {  		if (errs >= 2) { -			printk("HPFS: Hotfixes not supported here, try chkdsk\n"); -			mark_dirty(s); +			pr_err("Hotfixes not supported here, try chkdsk\n"); +			mark_dirty(s, 0);  			goto bail4;  		}  		hpfs_error(s, "hotfixes not supported here, try chkdsk"); -		if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n"); -		else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n"); +		if (errs == 0) +			pr_err("Proceeding, but your filesystem will be probably corrupted by this driver...\n"); +		else +			pr_err("This driver may read bad files or crash when operating on disk with hotfixes.\n");  	} -	if (spareblock->n_dnode_spares != spareblock->n_dnode_spares_free) { +	if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {  		if (errs >= 2) { -			printk("HPFS: Spare dnodes used, try chkdsk\n"); -			mark_dirty(s); +			pr_err("Spare dnodes used, try chkdsk\n"); +			mark_dirty(s, 0);  			goto bail4;  		}  		hpfs_error(s, "warning: spare dnodes used, try chkdsk"); -		if (errs == 0) printk("HPFS: Proceeding, but your filesystem could be corrupted if you delete files or directories\n"); +		if (errs == 0) +			pr_err("Proceeding, but your filesystem could be corrupted if you delete files or directories\n");  	}  	if (chk) {  		unsigned a; -		if (superblock->dir_band_end - superblock->dir_band_start + 1 != superblock->n_dir_band || -		    superblock->dir_band_end < superblock->dir_band_start || superblock->n_dir_band > 0x4000) { +		if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) || +		    le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) {  			hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x", -				superblock->dir_band_start, superblock->dir_band_end, superblock->n_dir_band); +				le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band));  			goto bail4;  		}  		a = sbi->sb_dirband_size;  		sbi->sb_dirband_size = 0; -		if (hpfs_chk_sectors(s, superblock->dir_band_start, superblock->n_dir_band, "dir_band") || -		    hpfs_chk_sectors(s, superblock->dir_band_bitmap, 4, "dir_band_bitmap") || -		    hpfs_chk_sectors(s, superblock->bitmaps, 4, "bitmaps")) { -			mark_dirty(s); +		if (hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") || +		    hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") || +		    hpfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) { +			mark_dirty(s, 0);  			goto bail4;  		}  		sbi->sb_dirband_size = a; -	} else printk("HPFS: You really don't want any checks? You are crazy...\n"); +	} else +		pr_err("You really don't want any checks? You are crazy...\n");  	/* Load code page table */ -	if (spareblock->n_code_pages) -		if (!(sbi->sb_cp_table = hpfs_load_code_page(s, spareblock->code_page_dir))) -			printk("HPFS: Warning: code page support is disabled\n"); +	if (le32_to_cpu(spareblock->n_code_pages)) +		if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir)))) +			pr_err("code page support is disabled\n");  	brelse(bh2);  	brelse(bh1); @@ -639,12 +671,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	hpfs_init_inode(root);  	hpfs_read_inode(root);  	unlock_new_inode(root); -	s->s_root = d_alloc_root(root); -	if (!s->s_root) { -		iput(root); +	s->s_root = d_make_root(root); +	if (!s->s_root)  		goto bail0; -	} -	hpfs_set_dentry_operations(s->s_root);  	/*  	 * find the root directory's . pointer & finish filling in the inode @@ -656,13 +685,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  	if (!de)  		hpfs_error(s, "unable to find root dir");  	else { -		root->i_atime.tv_sec = local_to_gmt(s, de->read_date); +		root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date));  		root->i_atime.tv_nsec = 0; -		root->i_mtime.tv_sec = local_to_gmt(s, de->write_date); +		root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date));  		root->i_mtime.tv_nsec = 0; -		root->i_ctime.tv_sec = local_to_gmt(s, de->creation_date); +		root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));  		root->i_ctime.tv_nsec = 0; -		hpfs_i(root)->i_ea_size = de->ea_size; +		hpfs_i(root)->i_ea_size = le32_to_cpu(de->ea_size);  		hpfs_i(root)->i_parent_dir = root->i_ino;  		if (root->i_size == -1)  			root->i_size = 2048; @@ -670,7 +699,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)  			root->i_blocks = 5;  		hpfs_brelse4(&qbh);  	} -	unlock_kernel(); +	hpfs_unlock(s);  	return 0;  bail4:	brelse(bh2); @@ -678,11 +707,8 @@ bail3:	brelse(bh1);  bail2:	brelse(bh0);  bail1:  bail0: -	kfree(sbi->sb_bmp_dir); -	kfree(sbi->sb_cp_table); -	s->s_fs_info = NULL; -	kfree(sbi); -	unlock_kernel(); +	hpfs_unlock(s); +	free_sbi(sbi);  	return -EINVAL;  } @@ -699,6 +725,7 @@ static struct file_system_type hpfs_fs_type = {  	.kill_sb	= kill_block_super,  	.fs_flags	= FS_REQUIRES_DEV,  }; +MODULE_ALIAS_FS("hpfs");  static int __init init_hpfs_fs(void)  {  | 
