Commit 31cb962e authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sysvfs endianness annotations and bugfixes

missing fs32_to_cpu() for on-disk ->s_type.
Signed-off-by: default avatarAl Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 211b9c02
......@@ -27,23 +27,23 @@
sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
but we nevertheless keep it up to date. */
static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
static inline sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh)
{
char *bh_data = bh->b_data;
if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
return (u32*)(bh_data+4);
return (sysv_zone_t*)(bh_data+4);
else
return (u32*)(bh_data+2);
return (sysv_zone_t*)(bh_data+2);
}
/* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
void sysv_free_block(struct super_block * sb, u32 nr)
void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
{
struct sysv_sb_info * sbi = SYSV_SB(sb);
struct buffer_head * bh;
u32 *blocks = sbi->s_bcache;
sysv_zone_t *blocks = sbi->s_bcache;
unsigned count;
unsigned block = fs32_to_cpu(sbi, nr);
......@@ -81,7 +81,7 @@ void sysv_free_block(struct super_block * sb, u32 nr)
return;
}
memset(bh->b_data, 0, sb->s_blocksize);
*(u16*)bh->b_data = cpu_to_fs16(sbi, count);
*(__fs16*)bh->b_data = cpu_to_fs16(sbi, count);
memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
mark_buffer_dirty(bh);
set_buffer_uptodate(bh);
......@@ -96,11 +96,11 @@ void sysv_free_block(struct super_block * sb, u32 nr)
unlock_super(sb);
}
u32 sysv_new_block(struct super_block * sb)
sysv_zone_t sysv_new_block(struct super_block * sb)
{
struct sysv_sb_info *sbi = SYSV_SB(sb);
unsigned int block;
u32 nr;
sysv_zone_t nr;
struct buffer_head * bh;
unsigned count;
......@@ -133,7 +133,7 @@ u32 sysv_new_block(struct super_block * sb)
*sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
goto Enospc;
}
count = fs16_to_cpu(sbi, *(u16*)bh->b_data);
count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
if (count > sbi->s_flc_size) {
printk("sysv_new_block: free-list block with >flc_size entries\n");
brelse(bh);
......@@ -161,7 +161,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
int sb_count;
int count;
struct buffer_head * bh = NULL;
u32 *blocks;
sysv_zone_t *blocks;
unsigned block;
int n;
......@@ -184,15 +184,16 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
blocks = sbi->s_bcache;
while (1) {
sysv_zone_t zone;
if (n > sbi->s_flc_size)
goto E2big;
block = 0;
while (n && (block = blocks[--n]) != 0)
zone = 0;
while (n && (zone = blocks[--n]) != 0)
count++;
if (block == 0)
if (zone == 0)
break;
block = fs32_to_cpu(sbi, block);
block = fs32_to_cpu(sbi, zone);
if (bh)
brelse(bh);
......@@ -202,7 +203,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
bh = sb_bread(sb, block);
if (!bh)
goto Eio;
n = fs16_to_cpu(sbi, *(u16*)bh->b_data);
n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
blocks = get_chunk(sb, bh);
}
if (bh)
......
......@@ -137,7 +137,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
struct super_block *sb = dir->i_sb;
struct sysv_sb_info *sbi = SYSV_SB(sb);
struct inode *inode;
u16 ino;
sysv_ino_t ino;
unsigned count;
inode = new_inode(sb);
......
......@@ -50,20 +50,20 @@ static int block_to_path(struct inode *inode, long block, int offsets[DEPTH])
return n;
}
static inline int block_to_cpu(struct sysv_sb_info *sbi, u32 nr)
static inline int block_to_cpu(struct sysv_sb_info *sbi, sysv_zone_t nr)
{
return sbi->s_block_base + fs32_to_cpu(sbi, nr);
}
typedef struct {
u32 *p;
u32 key;
sysv_zone_t *p;
sysv_zone_t key;
struct buffer_head *bh;
} Indirect;
static rwlock_t pointers_lock = RW_LOCK_UNLOCKED;
static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
static inline void add_chain(Indirect *p, struct buffer_head *bh, sysv_zone_t *v)
{
p->key = *(p->p = v);
p->bh = bh;
......@@ -76,9 +76,9 @@ static inline int verify_chain(Indirect *from, Indirect *to)
return (from > to);
}
static inline u32 *block_end(struct buffer_head *bh)
static inline sysv_zone_t *block_end(struct buffer_head *bh)
{
return (u32*)((char*)bh->b_data + bh->b_size);
return (sysv_zone_t*)((char*)bh->b_data + bh->b_size);
}
/*
......@@ -105,7 +105,7 @@ static Indirect *get_branch(struct inode *inode,
goto failure;
if (!verify_chain(chain, p))
goto changed;
add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
add_chain(++p, bh, (sysv_zone_t*)bh->b_data + *++offsets);
if (!p->key)
goto no_block;
}
......@@ -147,7 +147,7 @@ static int alloc_branch(struct inode *inode,
lock_buffer(bh);
memset(bh->b_data, 0, blocksize);
branch[n].bh = bh;
branch[n].p = (u32*) bh->b_data + offsets[n];
branch[n].p = (sysv_zone_t*) bh->b_data + offsets[n];
*branch[n].p = branch[n].key;
set_buffer_uptodate(bh);
unlock_buffer(bh);
......@@ -265,7 +265,7 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b
goto reread;
}
static inline int all_zeroes(u32 *p, u32 *q)
static inline int all_zeroes(sysv_zone_t *p, sysv_zone_t *q)
{
while (p < q)
if (*p++)
......@@ -277,7 +277,7 @@ static Indirect *find_shared(struct inode *inode,
int depth,
int offsets[],
Indirect chain[],
u32 *top)
sysv_zone_t *top)
{
Indirect *partial, *p;
int k, err;
......@@ -298,7 +298,7 @@ static Indirect *find_shared(struct inode *inode,
write_unlock(&pointers_lock);
goto no_top;
}
for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
for (p=partial; p>chain && all_zeroes((sysv_zone_t*)p->bh->b_data,p->p); p--)
;
/*
* OK, we've found the last block that must survive. The rest of our
......@@ -322,10 +322,10 @@ static Indirect *find_shared(struct inode *inode,
return partial;
}
static inline void free_data(struct inode *inode, u32 *p, u32 *q)
static inline void free_data(struct inode *inode, sysv_zone_t *p, sysv_zone_t *q)
{
for ( ; p < q ; p++) {
u32 nr = *p;
sysv_zone_t nr = *p;
if (nr) {
*p = 0;
sysv_free_block(inode->i_sb, nr);
......@@ -334,7 +334,7 @@ static inline void free_data(struct inode *inode, u32 *p, u32 *q)
}
}
static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
static void free_branches(struct inode *inode, sysv_zone_t *p, sysv_zone_t *q, int depth)
{
struct buffer_head * bh;
struct super_block *sb = inode->i_sb;
......@@ -342,7 +342,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
if (depth--) {
for ( ; p < q ; p++) {
int block;
u32 nr = *p;
sysv_zone_t nr = *p;
if (!nr)
continue;
*p = 0;
......@@ -350,7 +350,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
bh = sb_bread(sb, block);
if (!bh)
continue;
free_branches(inode, (u32*)bh->b_data,
free_branches(inode, (sysv_zone_t*)bh->b_data,
block_end(bh), depth);
bforget(bh);
sysv_free_block(sb, nr);
......@@ -362,11 +362,11 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
void sysv_truncate (struct inode * inode)
{
u32 *i_data = SYSV_I(inode)->i_data;
sysv_zone_t *i_data = SYSV_I(inode)->i_data;
int offsets[DEPTH];
Indirect chain[DEPTH];
Indirect *partial;
int nr = 0;
sysv_zone_t nr = 0;
int n;
long iblock;
unsigned blocksize;
......
......@@ -178,16 +178,22 @@ static void detected_v7(struct sysv_sb_info *sbi)
static int detect_xenix(struct sysv_sb_info *sbi, struct buffer_head *bh)
{
struct xenix_super_block *sbd = (struct xenix_super_block *)bh->b_data;
if (sbd->s_magic == cpu_to_le32(0x2b5544))
if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0x2b5544))
sbi->s_bytesex = BYTESEX_LE;
else if (sbd->s_magic == cpu_to_be32(0x2b5544))
else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0x2b5544))
sbi->s_bytesex = BYTESEX_BE;
else
return 0;
if (sbd->s_type > 2 || sbd->s_type < 1)
return 0;
switch (fs32_to_cpu(sbi, sbd->s_type)) {
case 1:
sbi->s_type = FSTYPE_XENIX;
return 1;
case 2:
sbi->s_type = FSTYPE_XENIX;
return sbd->s_type;
return 2;
default:
return 0;
}
}
static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
......@@ -195,15 +201,18 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
struct super_block *sb = sbi->s_sb;
/* All relevant fields are at the same offsets in R2 and R4 */
struct sysv4_super_block * sbd;
u32 type;
sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
if (sbd->s_magic == cpu_to_le32(0xfd187e20))
if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0xfd187e20))
sbi->s_bytesex = BYTESEX_LE;
else if (sbd->s_magic == cpu_to_be32(0xfd187e20))
else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0xfd187e20))
sbi->s_bytesex = BYTESEX_BE;
else
return 0;
type = fs32_to_cpu(sbi, sbd->s_type);
if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) {
sbi->s_type = FSTYPE_AFS;
sbi->s_forced_ro = 1;
......@@ -212,18 +221,17 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
"forcing read-only mode.\n",
sb->s_id);
}
return sbd->s_type;
return type;
}
if (fs32_to_cpu(sbi, sbd->s_time) < JAN_1_1980) {
/* this is likely to happen on SystemV2 FS */
if (sbd->s_type > 3 || sbd->s_type < 1)
if (type > 3 || type < 1)
return 0;
sbi->s_type = FSTYPE_SYSV2;
return sbd->s_type;
return type;
}
if ((sbd->s_type > 3 || sbd->s_type < 1) &&
(sbd->s_type > 0x30 || sbd->s_type < 0x10))
if ((type > 3 || type < 1) && (type > 0x30 || type < 0x10))
return 0;
/* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10,
......@@ -231,14 +239,14 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
filename limit is gone. Due to lack of information about this
feature read-only mode seems to be a reasonable approach... -KGB */
if (sbd->s_type >= 0x10) {
if (type >= 0x10) {
printk("SysV FS: can't handle long file names on %s, "
"forcing read-only mode.\n", sb->s_id);
sbi->s_forced_ro = 1;
}
sbi->s_type = FSTYPE_SYSV4;
return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type;
return type >= 0x10 ? type >> 4 : type;
}
static int detect_coherent(struct sysv_sb_info *sbi, struct buffer_head *bh)
......
......@@ -2,6 +2,10 @@
#define _SYSV_H
#include <linux/buffer_head.h>
typedef __u16 __bitwise __fs16;
typedef __u32 __bitwise __fs32;
#include <linux/sysv_fs.h>
/*
......@@ -38,14 +42,14 @@ struct sysv_sb_info {
different superblock layout. */
char * s_sbd1; /* entire superblock data, for part 1 */
char * s_sbd2; /* entire superblock data, for part 2 */
u16 *s_sb_fic_count; /* pointer to s_sbd->s_ninode */
u16 *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
u16 *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
u16 *s_bcache_count; /* pointer to s_sbd->s_nfree */
u32 *s_bcache; /* pointer to s_sbd->s_free */
u32 *s_free_blocks; /* pointer to s_sbd->s_tfree */
u32 *s_sb_time; /* pointer to s_sbd->s_time */
u32 *s_sb_state; /* pointer to s_sbd->s_state, only FSTYPE_SYSV */
__fs16 *s_sb_fic_count; /* pointer to s_sbd->s_ninode */
sysv_ino_t *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
__fs16 *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
__fs16 *s_bcache_count; /* pointer to s_sbd->s_nfree */
sysv_zone_t *s_bcache; /* pointer to s_sbd->s_free */
__fs32 *s_free_blocks; /* pointer to s_sbd->s_tfree */
__fs32 *s_sb_time; /* pointer to s_sbd->s_time */
__fs32 *s_sb_state; /* pointer to s_sbd->s_state, only FSTYPE_SYSV */
/* We keep those superblock entities that don't change here;
this saves us an indirection and perhaps a conversion. */
u32 s_firstinodezone; /* index of first inode zone */
......@@ -61,7 +65,7 @@ struct sysv_sb_info {
* SystemV/V7/Coherent FS inode data in memory
*/
struct sysv_inode_info {
u32 i_data[13];
__fs32 i_data[13];
u32 i_dir_start_lookup;
struct inode vfs_inode;
};
......@@ -126,8 +130,8 @@ extern void sysv_free_inode(struct inode *);
extern unsigned long sysv_count_free_inodes(struct super_block *);
/* balloc.c */
extern u32 sysv_new_block(struct super_block *);
extern void sysv_free_block(struct super_block *, u32);
extern sysv_zone_t sysv_new_block(struct super_block *);
extern void sysv_free_block(struct super_block *, sysv_zone_t);
extern unsigned long sysv_count_free_blocks(struct super_block *);
/* itree.c */
......@@ -181,58 +185,60 @@ static inline u32 PDP_swab(u32 x)
#endif
}
static inline u32 fs32_to_cpu(struct sysv_sb_info *sbi, u32 n)
static inline __u32 fs32_to_cpu(struct sysv_sb_info *sbi, __fs32 n)
{
if (sbi->s_bytesex == BYTESEX_PDP)
return PDP_swab(n);
return PDP_swab((__force __u32)n);
else if (sbi->s_bytesex == BYTESEX_LE)
return le32_to_cpu(n);
return le32_to_cpu((__force __le32)n);
else
return be32_to_cpu(n);
return be32_to_cpu((__force __be32)n);
}
static inline u32 cpu_to_fs32(struct sysv_sb_info *sbi, u32 n)
static inline __fs32 cpu_to_fs32(struct sysv_sb_info *sbi, __u32 n)
{
if (sbi->s_bytesex == BYTESEX_PDP)
return PDP_swab(n);
return (__force __fs32)PDP_swab(n);
else if (sbi->s_bytesex == BYTESEX_LE)
return cpu_to_le32(n);
return (__force __fs32)cpu_to_le32(n);
else
return cpu_to_be32(n);
return (__force __fs32)cpu_to_be32(n);
}
static inline u32 fs32_add(struct sysv_sb_info *sbi, u32 *n, int d)
static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d)
{
if (sbi->s_bytesex == BYTESEX_PDP)
return *n = PDP_swab(PDP_swab(*n)+d);
*(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d);
else if (sbi->s_bytesex == BYTESEX_LE)
return *n = cpu_to_le32(le32_to_cpu(*n)+d);
*(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d);
else
return *n = cpu_to_be32(be32_to_cpu(*n)+d);
*(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d);
return *n;
}
static inline u16 fs16_to_cpu(struct sysv_sb_info *sbi, u16 n)
static inline __u16 fs16_to_cpu(struct sysv_sb_info *sbi, __fs16 n)
{
if (sbi->s_bytesex != BYTESEX_BE)
return le16_to_cpu(n);
return le16_to_cpu((__force __le16)n);
else
return be16_to_cpu(n);
return be16_to_cpu((__force __be16)n);
}
static inline u16 cpu_to_fs16(struct sysv_sb_info *sbi, u16 n)
static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n)
{
if (sbi->s_bytesex != BYTESEX_BE)
return cpu_to_le16(n);
return (__force __fs16)cpu_to_le16(n);
else
return cpu_to_be16(n);
return (__force __fs16)cpu_to_be16(n);
}
static inline u16 fs16_add(struct sysv_sb_info *sbi, u16 *n, int d)
static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d)
{
if (sbi->s_bytesex != BYTESEX_BE)
return *n = cpu_to_le16(le16_to_cpu(*n)+d);
*(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
else
return *n = cpu_to_be16(be16_to_cpu(*n)+d);
*(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
return *n;
}
#endif /* _SYSV_H */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment