freevxfs: handle big endian HP-UX file systems

To support VxFS filesystems from HP-UX on x86 systems we need to
implement byte swapping, and to keep support for Unixware filesystems
it needs to be the complicated dual-endian kind ala sysvfs.

To do this properly we have to split the on disk and in-core inode
so that we can keep the in-core one in native endianness.  All other
structures are byteswapped on demand.

Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
[hch: make spare happy]
Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Krzysztof Błaszkowski
2016-05-31 08:45:13 +02:00
committed by Christoph Hellwig
parent 6b15d6650c
commit 0d83f7fc83
11 changed files with 405 additions and 277 deletions

View File

@@ -74,9 +74,10 @@ dir_blocks(struct inode *ip)
* len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
*/
static inline int
vxfs_match(int len, const char * const name, struct vxfs_direct *de)
vxfs_match(struct vxfs_sb_info *sbi, int len, const char *const name,
struct vxfs_direct *de)
{
if (len != de->d_namelen)
if (len != fs16_to_cpu(sbi, de->d_namelen))
return 0;
if (!de->d_ino)
return 0;
@@ -84,9 +85,10 @@ vxfs_match(int len, const char * const name, struct vxfs_direct *de)
}
static inline struct vxfs_direct *
vxfs_next_entry(struct vxfs_direct *de)
vxfs_next_entry(struct vxfs_sb_info *sbi, struct vxfs_direct *de)
{
return ((struct vxfs_direct *)((char*)de + de->d_reclen));
return ((struct vxfs_direct *)
((char *)de + fs16_to_cpu(sbi, de->d_reclen)));
}
/**
@@ -106,6 +108,7 @@ vxfs_next_entry(struct vxfs_direct *de)
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
u_long npages, page, nblocks, pblocks, block;
u_long bsize = ip->i_sb->s_blocksize;
const char *name = dp->d_name.name;
@@ -133,14 +136,16 @@ vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
limit = baddr + bsize - VXFS_DIRLEN(1);
dbp = (struct vxfs_dirblk *)baddr;
de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
de = (struct vxfs_direct *)
(baddr + VXFS_DIRBLKOV(sbi, dbp));
for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
for (; (caddr_t)de <= limit;
de = vxfs_next_entry(sbi, de)) {
if (!de->d_reclen)
break;
if (!de->d_ino)
continue;
if (vxfs_match(namelen, name, de)) {
if (vxfs_match(sbi, namelen, name, de)) {
*ppp = pp;
return (de);
}
@@ -173,7 +178,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
de = vxfs_find_entry(dip, dp, &pp);
if (de) {
ino = de->d_ino;
ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
kunmap(pp);
put_page(pp);
}
@@ -232,10 +237,12 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
{
struct inode *ip = file_inode(fp);
struct super_block *sbp = ip->i_sb;
struct vxfs_sb_info *sbi = VXFS_SBI(sbp);
u_long bsize = sbp->s_blocksize;
u_long page, npages, block, pblocks, nblocks, offset;
loff_t pos;
if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx))
return 0;
@@ -280,9 +287,10 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
de = (struct vxfs_direct *)
(offset ?
(kaddr + offset) :
(baddr + VXFS_DIRBLKOV(dbp)));
(baddr + VXFS_DIRBLKOV(sbi, dbp)));
for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
for (; (char *)de <= limit;
de = vxfs_next_entry(sbi, de)) {
if (!de->d_reclen)
break;
if (!de->d_ino)
@@ -290,8 +298,10 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
offset = (char *)de - kaddr;
ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
if (!dir_emit(ctx, de->d_name, de->d_namelen,
de->d_ino, DT_UNKNOWN)) {
if (!dir_emit(ctx, de->d_name,
fs16_to_cpu(sbi, de->d_namelen),
fs32_to_cpu(sbi, de->d_ino),
DT_UNKNOWN)) {
vxfs_put_page(pp);
return 0;
}