aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 14:56:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 14:56:29 -0400
commit0a7736d03720a450727c6ab906e13b60d4d34e42 (patch)
treec3ddbf0e3dc9ac7273a2cf8d639d83bdf20481d4
parenta54809f1167243d909b2c63fcd51e1d648deeb01 (diff)
parentbf1bb4b460c8dc3a33793bff21464a9d816697ad (diff)
Merge tag 'freevxfs-for-4.8' of git://git.infradead.org/users/hch/freevxfs
Pull freevxfs updates from Christoph Hellwig: "Support for foreign endianess and HP-UP superblocks from Krzysztof Błaszkowski" * tag 'freevxfs-for-4.8' of git://git.infradead.org/users/hch/freevxfs: freevxfs: update Kconfig information freevxfs: refactor readdir and lookup code freevxfs: fix lack of inode initialization freevxfs: fix memory leak in vxfs_read_fshead() freevxfs: update documentation and cresdits for HP-UX support freevxfs: implement ->alloc_inode and ->destroy_inode freevxfs: avoid the need for forward declaring the super operations freevxfs: move VFS inode allocation into vxfs_blkiget and vxfs_stiget freevxfs: remove vxfs_put_fake_inode freevxfs: handle big endian HP-UX file systems
-rw-r--r--fs/freevxfs/Kconfig13
-rw-r--r--fs/freevxfs/vxfs.h185
-rw-r--r--fs/freevxfs/vxfs_bmap.c70
-rw-r--r--fs/freevxfs/vxfs_dir.h17
-rw-r--r--fs/freevxfs/vxfs_extern.h10
-rw-r--r--fs/freevxfs/vxfs_fshead.c37
-rw-r--r--fs/freevxfs/vxfs_fshead.h29
-rw-r--r--fs/freevxfs/vxfs_inode.c265
-rw-r--r--fs/freevxfs/vxfs_inode.h146
-rw-r--r--fs/freevxfs/vxfs_lookup.c226
-rw-r--r--fs/freevxfs/vxfs_olt.c15
-rw-r--r--fs/freevxfs/vxfs_olt.h70
-rw-r--r--fs/freevxfs/vxfs_super.c162
13 files changed, 661 insertions, 584 deletions
diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig
index 8dc1cd5c1efe..ce49df1020dd 100644
--- a/fs/freevxfs/Kconfig
+++ b/fs/freevxfs/Kconfig
@@ -5,12 +5,21 @@ config VXFS_FS
5 FreeVxFS is a file system driver that support the VERITAS VxFS(TM) 5 FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
6 file system format. VERITAS VxFS(TM) is the standard file system 6 file system format. VERITAS VxFS(TM) is the standard file system
7 of SCO UnixWare (and possibly others) and optionally available 7 of SCO UnixWare (and possibly others) and optionally available
8 for Sunsoft Solaris, HP-UX and many other operating systems. 8 for Sunsoft Solaris, HP-UX and many other operating systems. However
9 Currently only readonly access is supported. 9 these particular OS implementations of vxfs may differ in on-disk
10 data endianess and/or superblock offset. The vxfs module has been
11 tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
12 Currently only readonly access is supported and VxFX versions
13 2, 3 and 4. Tests were performed with HP-UX VxFS version 3.
10 14
11 NOTE: the file system type as used by mount(1), mount(2) and 15 NOTE: the file system type as used by mount(1), mount(2) and
12 fstab(5) is 'vxfs' as it describes the file system format, not 16 fstab(5) is 'vxfs' as it describes the file system format, not
13 the actual driver. 17 the actual driver.
14 18
19 There is a userspace utility for HP-UX logical volumes which makes
20 creating HP-UX logical volumes easy from HP-UX disk block device file
21 or regular file with image of the disk. See:
22 https://sourceforge.net/projects/linux-vxfs/
23
15 To compile this as a module, choose M here: the module will be 24 To compile this as a module, choose M here: the module will be
16 called freevxfs. If unsure, say N. 25 called freevxfs. If unsure, say N.
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a92652612a..a41ea0ba6943 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -38,13 +39,6 @@
38 */ 39 */
39#include <linux/types.h> 40#include <linux/types.h>
40 41
41
42/*
43 * Data types for use with the VxFS ondisk format.
44 */
45typedef int32_t vx_daddr_t;
46typedef int32_t vx_ino_t;
47
48/* 42/*
49 * Superblock magic number (vxfs_super->vs_magic). 43 * Superblock magic number (vxfs_super->vs_magic).
50 */ 44 */
@@ -60,6 +54,14 @@ typedef int32_t vx_ino_t;
60 */ 54 */
61#define VXFS_NEFREE 32 55#define VXFS_NEFREE 32
62 56
57enum vxfs_byte_order {
58 VXFS_BO_LE,
59 VXFS_BO_BE,
60};
61
62typedef __u16 __bitwise __fs16;
63typedef __u32 __bitwise __fs32;
64typedef __u64 __bitwise __fs64;
63 65
64/* 66/*
65 * VxFS superblock (disk). 67 * VxFS superblock (disk).
@@ -71,83 +73,83 @@ struct vxfs_sb {
71 * Lots of this fields are no more used by version 2 73 * Lots of this fields are no more used by version 2
72 * and never filesystems. 74 * and never filesystems.
73 */ 75 */
74 u_int32_t vs_magic; /* Magic number */ 76 __fs32 vs_magic; /* Magic number */
75 int32_t vs_version; /* VxFS version */ 77 __fs32 vs_version; /* VxFS version */
76 u_int32_t vs_ctime; /* create time - secs */ 78 __fs32 vs_ctime; /* create time - secs */
77 u_int32_t vs_cutime; /* create time - usecs */ 79 __fs32 vs_cutime; /* create time - usecs */
78 int32_t __unused1; /* unused */ 80 __fs32 __unused1; /* unused */
79 int32_t __unused2; /* unused */ 81 __fs32 __unused2; /* unused */
80 vx_daddr_t vs_old_logstart; /* obsolete */ 82 __fs32 vs_old_logstart; /* obsolete */
81 vx_daddr_t vs_old_logend; /* obsolete */ 83 __fs32 vs_old_logend; /* obsolete */
82 int32_t vs_bsize; /* block size */ 84 __fs32 vs_bsize; /* block size */
83 int32_t vs_size; /* number of blocks */ 85 __fs32 vs_size; /* number of blocks */
84 int32_t vs_dsize; /* number of data blocks */ 86 __fs32 vs_dsize; /* number of data blocks */
85 u_int32_t vs_old_ninode; /* obsolete */ 87 __fs32 vs_old_ninode; /* obsolete */
86 int32_t vs_old_nau; /* obsolete */ 88 __fs32 vs_old_nau; /* obsolete */
87 int32_t __unused3; /* unused */ 89 __fs32 __unused3; /* unused */
88 int32_t vs_old_defiextsize; /* obsolete */ 90 __fs32 vs_old_defiextsize; /* obsolete */
89 int32_t vs_old_ilbsize; /* obsolete */ 91 __fs32 vs_old_ilbsize; /* obsolete */
90 int32_t vs_immedlen; /* size of immediate data area */ 92 __fs32 vs_immedlen; /* size of immediate data area */
91 int32_t vs_ndaddr; /* number of direct extentes */ 93 __fs32 vs_ndaddr; /* number of direct extentes */
92 vx_daddr_t vs_firstau; /* address of first AU */ 94 __fs32 vs_firstau; /* address of first AU */
93 vx_daddr_t vs_emap; /* offset of extent map in AU */ 95 __fs32 vs_emap; /* offset of extent map in AU */
94 vx_daddr_t vs_imap; /* offset of inode map in AU */ 96 __fs32 vs_imap; /* offset of inode map in AU */
95 vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */ 97 __fs32 vs_iextop; /* offset of ExtOp. map in AU */
96 vx_daddr_t vs_istart; /* offset of inode list in AU */ 98 __fs32 vs_istart; /* offset of inode list in AU */
97 vx_daddr_t vs_bstart; /* offset of fdblock in AU */ 99 __fs32 vs_bstart; /* offset of fdblock in AU */
98 vx_daddr_t vs_femap; /* aufirst + emap */ 100 __fs32 vs_femap; /* aufirst + emap */
99 vx_daddr_t vs_fimap; /* aufirst + imap */ 101 __fs32 vs_fimap; /* aufirst + imap */
100 vx_daddr_t vs_fiextop; /* aufirst + iextop */ 102 __fs32 vs_fiextop; /* aufirst + iextop */
101 vx_daddr_t vs_fistart; /* aufirst + istart */ 103 __fs32 vs_fistart; /* aufirst + istart */
102 vx_daddr_t vs_fbstart; /* aufirst + bstart */ 104 __fs32 vs_fbstart; /* aufirst + bstart */
103 int32_t vs_nindir; /* number of entries in indir */ 105 __fs32 vs_nindir; /* number of entries in indir */
104 int32_t vs_aulen; /* length of AU in blocks */ 106 __fs32 vs_aulen; /* length of AU in blocks */
105 int32_t vs_auimlen; /* length of imap in blocks */ 107 __fs32 vs_auimlen; /* length of imap in blocks */
106 int32_t vs_auemlen; /* length of emap in blocks */ 108 __fs32 vs_auemlen; /* length of emap in blocks */
107 int32_t vs_auilen; /* length of ilist in blocks */ 109 __fs32 vs_auilen; /* length of ilist in blocks */
108 int32_t vs_aupad; /* length of pad in blocks */ 110 __fs32 vs_aupad; /* length of pad in blocks */
109 int32_t vs_aublocks; /* data blocks in AU */ 111 __fs32 vs_aublocks; /* data blocks in AU */
110 int32_t vs_maxtier; /* log base 2 of aublocks */ 112 __fs32 vs_maxtier; /* log base 2 of aublocks */
111 int32_t vs_inopb; /* number of inodes per blk */ 113 __fs32 vs_inopb; /* number of inodes per blk */
112 int32_t vs_old_inopau; /* obsolete */ 114 __fs32 vs_old_inopau; /* obsolete */
113 int32_t vs_old_inopilb; /* obsolete */ 115 __fs32 vs_old_inopilb; /* obsolete */
114 int32_t vs_old_ndiripau; /* obsolete */ 116 __fs32 vs_old_ndiripau; /* obsolete */
115 int32_t vs_iaddrlen; /* size of indirect addr ext. */ 117 __fs32 vs_iaddrlen; /* size of indirect addr ext. */
116 int32_t vs_bshift; /* log base 2 of bsize */ 118 __fs32 vs_bshift; /* log base 2 of bsize */
117 int32_t vs_inoshift; /* log base 2 of inobp */ 119 __fs32 vs_inoshift; /* log base 2 of inobp */
118 int32_t vs_bmask; /* ~( bsize - 1 ) */ 120 __fs32 vs_bmask; /* ~( bsize - 1 ) */
119 int32_t vs_boffmask; /* bsize - 1 */ 121 __fs32 vs_boffmask; /* bsize - 1 */
120 int32_t vs_old_inomask; /* old_inopilb - 1 */ 122 __fs32 vs_old_inomask; /* old_inopilb - 1 */
121 int32_t vs_checksum; /* checksum of V1 data */ 123 __fs32 vs_checksum; /* checksum of V1 data */
122 124
123 /* 125 /*
124 * Version 1, writable 126 * Version 1, writable
125 */ 127 */
126 int32_t vs_free; /* number of free blocks */ 128 __fs32 vs_free; /* number of free blocks */
127 int32_t vs_ifree; /* number of free inodes */ 129 __fs32 vs_ifree; /* number of free inodes */
128 int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */ 130 __fs32 vs_efree[VXFS_NEFREE]; /* number of free extents by size */
129 int32_t vs_flags; /* flags ?!? */ 131 __fs32 vs_flags; /* flags ?!? */
130 u_int8_t vs_mod; /* filesystem has been changed */ 132 __u8 vs_mod; /* filesystem has been changed */
131 u_int8_t vs_clean; /* clean FS */ 133 __u8 vs_clean; /* clean FS */
132 u_int16_t __unused4; /* unused */ 134 __fs16 __unused4; /* unused */
133 u_int32_t vs_firstlogid; /* mount time log ID */ 135 __fs32 vs_firstlogid; /* mount time log ID */
134 u_int32_t vs_wtime; /* last time written - sec */ 136 __fs32 vs_wtime; /* last time written - sec */
135 u_int32_t vs_wutime; /* last time written - usec */ 137 __fs32 vs_wutime; /* last time written - usec */
136 u_int8_t vs_fname[6]; /* FS name */ 138 __u8 vs_fname[6]; /* FS name */
137 u_int8_t vs_fpack[6]; /* FS pack name */ 139 __u8 vs_fpack[6]; /* FS pack name */
138 int32_t vs_logversion; /* log format version */ 140 __fs32 vs_logversion; /* log format version */
139 int32_t __unused5; /* unused */ 141 __u32 __unused5; /* unused */
140 142
141 /* 143 /*
142 * Version 2, Read-only 144 * Version 2, Read-only
143 */ 145 */
144 vx_daddr_t vs_oltext[2]; /* OLT extent and replica */ 146 __fs32 vs_oltext[2]; /* OLT extent and replica */
145 int32_t vs_oltsize; /* OLT extent size */ 147 __fs32 vs_oltsize; /* OLT extent size */
146 int32_t vs_iauimlen; /* size of inode map */ 148 __fs32 vs_iauimlen; /* size of inode map */
147 int32_t vs_iausize; /* size of IAU in blocks */ 149 __fs32 vs_iausize; /* size of IAU in blocks */
148 int32_t vs_dinosize; /* size of inode in bytes */ 150 __fs32 vs_dinosize; /* size of inode in bytes */
149 int32_t vs_old_dniaddr; /* indir levels per inode */ 151 __fs32 vs_old_dniaddr; /* indir levels per inode */
150 int32_t vs_checksum2; /* checksum of V2 RO */ 152 __fs32 vs_checksum2; /* checksum of V2 RO */
151 153
152 /* 154 /*
153 * Actually much more... 155 * Actually much more...
@@ -168,8 +170,32 @@ struct vxfs_sb_info {
168 ino_t vsi_fshino; /* fileset header inode */ 170 ino_t vsi_fshino; /* fileset header inode */
169 daddr_t vsi_oltext; /* OLT extent */ 171 daddr_t vsi_oltext; /* OLT extent */
170 daddr_t vsi_oltsize; /* OLT size */ 172 daddr_t vsi_oltsize; /* OLT size */
173 enum vxfs_byte_order byte_order;
171}; 174};
172 175
176static inline u16 fs16_to_cpu(struct vxfs_sb_info *sbi, __fs16 a)
177{
178 if (sbi->byte_order == VXFS_BO_BE)
179 return be16_to_cpu((__force __be16)a);
180 else
181 return le16_to_cpu((__force __le16)a);
182}
183
184static inline u32 fs32_to_cpu(struct vxfs_sb_info *sbi, __fs32 a)
185{
186 if (sbi->byte_order == VXFS_BO_BE)
187 return be32_to_cpu((__force __be32)a);
188 else
189 return le32_to_cpu((__force __le32)a);
190}
191
192static inline u64 fs64_to_cpu(struct vxfs_sb_info *sbi, __fs64 a)
193{
194 if (sbi->byte_order == VXFS_BO_BE)
195 return be64_to_cpu((__force __be64)a);
196 else
197 return le64_to_cpu((__force __le64)a);
198}
173 199
174/* 200/*
175 * File modes. File types above 0xf000 are vxfs internal only, they should 201 * File modes. File types above 0xf000 are vxfs internal only, they should
@@ -247,13 +273,6 @@ enum {
247#define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) 273#define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
248#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) 274#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
249 275
250
251/*
252 * Get filesystem private data from VFS inode.
253 */
254#define VXFS_INO(ip) \
255 ((struct vxfs_inode_info *)(ip)->i_private)
256
257/* 276/*
258 * Get filesystem private data from VFS superblock. 277 * Get filesystem private data from VFS superblock.
259 */ 278 */
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3cacd5a..1fd41cf98b9f 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -68,8 +68,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
68{ 68{
69 struct super_block *sb = ip->i_sb; 69 struct super_block *sb = ip->i_sb;
70 struct vxfs_inode_info *vip = VXFS_INO(ip); 70 struct vxfs_inode_info *vip = VXFS_INO(ip);
71 struct vxfs_sb_info *sbi = VXFS_SBI(sb);
71 unsigned long bsize = sb->s_blocksize; 72 unsigned long bsize = sb->s_blocksize;
72 u32 indsize = vip->vii_ext4.ve4_indsize; 73 u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);
73 int i; 74 int i;
74 75
75 if (indsize > sb->s_blocksize) 76 if (indsize > sb->s_blocksize)
@@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
77 78
78 for (i = 0; i < VXFS_NDADDR; i++) { 79 for (i = 0; i < VXFS_NDADDR; i++) {
79 struct direct *d = vip->vii_ext4.ve4_direct + i; 80 struct direct *d = vip->vii_ext4.ve4_direct + i;
80 if (bn >= 0 && bn < d->size) 81 if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
81 return (bn + d->extent); 82 return (bn + fs32_to_cpu(sbi, d->extent));
82 bn -= d->size; 83 bn -= fs32_to_cpu(sbi, d->size);
83 } 84 }
84 85
85 if ((bn / (indsize * indsize * bsize / 4)) == 0) { 86 if ((bn / (indsize * indsize * bsize / 4)) == 0) {
86 struct buffer_head *buf; 87 struct buffer_head *buf;
87 daddr_t bno; 88 daddr_t bno;
88 u32 *indir; 89 __fs32 *indir;
89 90
90 buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]); 91 buf = sb_bread(sb,
92 fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));
91 if (!buf || !buffer_mapped(buf)) 93 if (!buf || !buffer_mapped(buf))
92 goto fail_buf; 94 goto fail_buf;
93 95
94 indir = (u32 *)buf->b_data; 96 indir = (__fs32 *)buf->b_data;
95 bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize); 97 bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
98 (bn % indsize);
96 99
97 brelse(buf); 100 brelse(buf);
98 return bno; 101 return bno;
@@ -127,6 +130,7 @@ fail_buf:
127static daddr_t 130static daddr_t
128vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) 131vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
129{ 132{
133 struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
130 struct buffer_head *bp = NULL; 134 struct buffer_head *bp = NULL;
131 daddr_t pblock = 0; 135 daddr_t pblock = 0;
132 int i; 136 int i;
@@ -142,24 +146,27 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
142 146
143 typ = ((struct vxfs_typed *)bp->b_data) + 147 typ = ((struct vxfs_typed *)bp->b_data) +
144 (i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); 148 (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
145 off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); 149 off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
146 150
147 if (block < off) { 151 if (block < off) {
148 brelse(bp); 152 brelse(bp);
149 continue; 153 continue;
150 } 154 }
151 155
152 switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { 156 switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>
157 VXFS_TYPED_TYPESHIFT)) {
153 case VXFS_TYPED_INDIRECT: 158 case VXFS_TYPED_INDIRECT:
154 pblock = vxfs_bmap_indir(ip, typ->vt_block, 159 pblock = vxfs_bmap_indir(ip,
155 typ->vt_size, block - off); 160 fs32_to_cpu(sbi, typ->vt_block),
161 fs32_to_cpu(sbi, typ->vt_size),
162 block - off);
156 if (pblock == -2) 163 if (pblock == -2)
157 break; 164 break;
158 goto out; 165 goto out;
159 case VXFS_TYPED_DATA: 166 case VXFS_TYPED_DATA:
160 if ((block - off) >= typ->vt_size) 167 if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
161 break; 168 break;
162 pblock = (typ->vt_block + block - off); 169 pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
163 goto out; 170 goto out;
164 case VXFS_TYPED_INDIRECT_DEV4: 171 case VXFS_TYPED_INDIRECT_DEV4:
165 case VXFS_TYPED_DATA_DEV4: { 172 case VXFS_TYPED_DATA_DEV4: {
@@ -167,13 +174,15 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
167 (struct vxfs_typed_dev4 *)typ; 174 (struct vxfs_typed_dev4 *)typ;
168 175
169 printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); 176 printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
170 printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", 177 printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
171 (unsigned long long) typ4->vd4_block, 178 fs64_to_cpu(sbi, typ4->vd4_block),
172 (unsigned long long) typ4->vd4_size, 179 fs64_to_cpu(sbi, typ4->vd4_size),
173 typ4->vd4_dev); 180 fs32_to_cpu(sbi, typ4->vd4_dev));
174 goto fail; 181 goto fail;
175 } 182 }
176 default: 183 default:
184 printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
185 __LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
177 BUG(); 186 BUG();
178 } 187 }
179 brelse(bp); 188 brelse(bp);
@@ -201,28 +210,33 @@ static daddr_t
201vxfs_bmap_typed(struct inode *ip, long iblock) 210vxfs_bmap_typed(struct inode *ip, long iblock)
202{ 211{
203 struct vxfs_inode_info *vip = VXFS_INO(ip); 212 struct vxfs_inode_info *vip = VXFS_INO(ip);
213 struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
204 daddr_t pblock = 0; 214 daddr_t pblock = 0;
205 int i; 215 int i;
206 216
207 for (i = 0; i < VXFS_NTYPED; i++) { 217 for (i = 0; i < VXFS_NTYPED; i++) {
208 struct vxfs_typed *typ = vip->vii_org.typed + i; 218 struct vxfs_typed *typ = vip->vii_org.typed + i;
209 int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); 219 u64 hdr = fs64_to_cpu(sbi, typ->vt_hdr);
220 int64_t off = (hdr & VXFS_TYPED_OFFSETMASK);
210 221
211#ifdef DIAGNOSTIC 222#ifdef DIAGNOSTIC
212 vxfs_typdump(typ); 223 vxfs_typdump(typ);
213#endif 224#endif
214 if (iblock < off) 225 if (iblock < off)
215 continue; 226 continue;
216 switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { 227 switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
217 case VXFS_TYPED_INDIRECT: 228 case VXFS_TYPED_INDIRECT:
218 pblock = vxfs_bmap_indir(ip, typ->vt_block, 229 pblock = vxfs_bmap_indir(ip,
219 typ->vt_size, iblock - off); 230 fs32_to_cpu(sbi, typ->vt_block),
231 fs32_to_cpu(sbi, typ->vt_size),
232 iblock - off);
220 if (pblock == -2) 233 if (pblock == -2)
221 break; 234 break;
222 return (pblock); 235 return (pblock);
223 case VXFS_TYPED_DATA: 236 case VXFS_TYPED_DATA:
224 if ((iblock - off) < typ->vt_size) 237 if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
225 return (typ->vt_block + iblock - off); 238 return (fs32_to_cpu(sbi, typ->vt_block) +
239 iblock - off);
226 break; 240 break;
227 case VXFS_TYPED_INDIRECT_DEV4: 241 case VXFS_TYPED_INDIRECT_DEV4:
228 case VXFS_TYPED_DATA_DEV4: { 242 case VXFS_TYPED_DATA_DEV4: {
@@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
230 (struct vxfs_typed_dev4 *)typ; 244 (struct vxfs_typed_dev4 *)typ;
231 245
232 printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); 246 printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
233 printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", 247 printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
234 (unsigned long long) typ4->vd4_block, 248 fs64_to_cpu(sbi, typ4->vd4_block),
235 (unsigned long long) typ4->vd4_size, 249 fs64_to_cpu(sbi, typ4->vd4_size),
236 typ4->vd4_dev); 250 fs32_to_cpu(sbi, typ4->vd4_dev));
237 return 0; 251 return 0;
238 } 252 }
239 default: 253 default:
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index aaf1fb098639..acc5477b3f23 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -48,9 +48,9 @@
48 * Linux driver for now. 48 * Linux driver for now.
49 */ 49 */
50struct vxfs_dirblk { 50struct vxfs_dirblk {
51 u_int16_t d_free; /* free space in dirblock */ 51 __fs16 d_free; /* free space in dirblock */
52 u_int16_t d_nhash; /* no of hash chains */ 52 __fs16 d_nhash; /* no of hash chains */
53 u_int16_t d_hash[1]; /* hash chain */ 53 __fs16 d_hash[1]; /* hash chain */
54}; 54};
55 55
56/* 56/*
@@ -63,10 +63,10 @@ struct vxfs_dirblk {
63 * VxFS directory entry. 63 * VxFS directory entry.
64 */ 64 */
65struct vxfs_direct { 65struct vxfs_direct {
66 vx_ino_t d_ino; /* inode number */ 66 __fs32 d_ino; /* inode number */
67 u_int16_t d_reclen; /* record length */ 67 __fs16 d_reclen; /* record length */
68 u_int16_t d_namelen; /* d_name length */ 68 __fs16 d_namelen; /* d_name length */
69 u_int16_t d_hashnext; /* next hash entry */ 69 __fs16 d_hashnext; /* next hash entry */
70 char d_name[VXFS_NAMELEN]; /* name */ 70 char d_name[VXFS_NAMELEN]; /* name */
71}; 71};
72 72
@@ -87,6 +87,7 @@ struct vxfs_direct {
87/* 87/*
88 * VXFS_DIRBLKOV is the overhead of a specific dirblock. 88 * VXFS_DIRBLKOV is the overhead of a specific dirblock.
89 */ 89 */
90#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4) 90#define VXFS_DIRBLKOV(sbi, dbp) \
91 ((sizeof(short) * fs16_to_cpu(sbi, dbp->d_nhash)) + 4)
91 92
92#endif /* _VXFS_DIR_H_ */ 93#endif /* _VXFS_DIR_H_ */
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index e3dcb4467d92..f5c428e21024 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -52,14 +52,10 @@ extern int vxfs_read_fshead(struct super_block *);
52 52
53/* vxfs_inode.c */ 53/* vxfs_inode.c */
54extern const struct address_space_operations vxfs_immed_aops; 54extern const struct address_space_operations vxfs_immed_aops;
55extern struct kmem_cache *vxfs_inode_cachep;
56extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); 55extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
57extern struct inode * vxfs_get_fake_inode(struct super_block *, 56extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
58 struct vxfs_inode_info *); 57extern struct inode *vxfs_stiget(struct super_block *, ino_t);
59extern void vxfs_put_fake_inode(struct inode *); 58extern struct inode *vxfs_iget(struct super_block *, ino_t);
60extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t);
61extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
62extern struct inode * vxfs_iget(struct super_block *, ino_t);
63extern void vxfs_evict_inode(struct inode *); 59extern void vxfs_evict_inode(struct inode *);
64 60
65/* vxfs_lookup.c */ 61/* vxfs_lookup.c */
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94e58e9..a4610a77649e 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -108,31 +109,26 @@ vxfs_read_fshead(struct super_block *sbp)
108{ 109{
109 struct vxfs_sb_info *infp = VXFS_SBI(sbp); 110 struct vxfs_sb_info *infp = VXFS_SBI(sbp);
110 struct vxfs_fsh *pfp, *sfp; 111 struct vxfs_fsh *pfp, *sfp;
111 struct vxfs_inode_info *vip, *tip; 112 struct vxfs_inode_info *vip;
112 113
113 vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); 114 infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
114 if (!vip) { 115 if (!infp->vsi_fship) {
115 printk(KERN_ERR "vxfs: unable to read fsh inode\n"); 116 printk(KERN_ERR "vxfs: unable to read fsh inode\n");
116 return -EINVAL; 117 return -EINVAL;
117 } 118 }
119
120 vip = VXFS_INO(infp->vsi_fship);
118 if (!VXFS_ISFSH(vip)) { 121 if (!VXFS_ISFSH(vip)) {
119 printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", 122 printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
120 vip->vii_mode & VXFS_TYPE_MASK); 123 vip->vii_mode & VXFS_TYPE_MASK);
121 goto out_free_fship; 124 goto out_iput_fship;
122 } 125 }
123 126
124
125#ifdef DIAGNOSTIC 127#ifdef DIAGNOSTIC
126 printk("vxfs: fsh inode dump:\n"); 128 printk("vxfs: fsh inode dump:\n");
127 vxfs_dumpi(vip, infp->vsi_fshino); 129 vxfs_dumpi(vip, infp->vsi_fshino);
128#endif 130#endif
129 131
130 infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
131 if (!infp->vsi_fship) {
132 printk(KERN_ERR "vxfs: unable to get fsh inode\n");
133 goto out_free_fship;
134 }
135
136 sfp = vxfs_getfsh(infp->vsi_fship, 0); 132 sfp = vxfs_getfsh(infp->vsi_fship, 0);
137 if (!sfp) { 133 if (!sfp) {
138 printk(KERN_ERR "vxfs: unable to get structural fsh\n"); 134 printk(KERN_ERR "vxfs: unable to get structural fsh\n");
@@ -153,14 +149,10 @@ vxfs_read_fshead(struct super_block *sbp)
153 vxfs_dumpfsh(pfp); 149 vxfs_dumpfsh(pfp);
154#endif 150#endif
155 151
156 tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); 152 infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext,
157 if (!tip) 153 fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
158 goto out_free_pfp;
159
160 infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
161 if (!infp->vsi_stilist) { 154 if (!infp->vsi_stilist) {
162 printk(KERN_ERR "vxfs: unable to get structural list inode\n"); 155 printk(KERN_ERR "vxfs: unable to get structural list inode\n");
163 kfree(tip);
164 goto out_free_pfp; 156 goto out_free_pfp;
165 } 157 }
166 if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { 158 if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -169,13 +161,9 @@ vxfs_read_fshead(struct super_block *sbp)
169 goto out_iput_stilist; 161 goto out_iput_stilist;
170 } 162 }
171 163
172 tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); 164 infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
173 if (!tip)
174 goto out_iput_stilist;
175 infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
176 if (!infp->vsi_ilist) { 165 if (!infp->vsi_ilist) {
177 printk(KERN_ERR "vxfs: unable to get inode list inode\n"); 166 printk(KERN_ERR "vxfs: unable to get inode list inode\n");
178 kfree(tip);
179 goto out_iput_stilist; 167 goto out_iput_stilist;
180 } 168 }
181 if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { 169 if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -184,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp)
184 goto out_iput_ilist; 172 goto out_iput_ilist;
185 } 173 }
186 174
175 kfree(pfp);
176 kfree(sfp);
187 return 0; 177 return 0;
188 178
189 out_iput_ilist: 179 out_iput_ilist:
@@ -197,7 +187,4 @@ vxfs_read_fshead(struct super_block *sbp)
197 out_iput_fship: 187 out_iput_fship:
198 iput(infp->vsi_fship); 188 iput(infp->vsi_fship);
199 return -EINVAL; 189 return -EINVAL;
200 out_free_fship:
201 kfree(vip);
202 return -EINVAL;
203} 190}
diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h
index ead0d640c181..e026f0c49159 100644
--- a/fs/freevxfs/vxfs_fshead.h
+++ b/fs/freevxfs/vxfs_fshead.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -42,20 +43,20 @@
42 * Fileset header 43 * Fileset header
43 */ 44 */
44struct vxfs_fsh { 45struct vxfs_fsh {
45 u_int32_t fsh_version; /* fileset header version */ 46 __fs32 fsh_version; /* fileset header version */
46 u_int32_t fsh_fsindex; /* fileset index */ 47 __fs32 fsh_fsindex; /* fileset index */
47 u_int32_t fsh_time; /* modification time - sec */ 48 __fs32 fsh_time; /* modification time - sec */
48 u_int32_t fsh_utime; /* modification time - usec */ 49 __fs32 fsh_utime; /* modification time - usec */
49 u_int32_t fsh_extop; /* extop flags */ 50 __fs32 fsh_extop; /* extop flags */
50 vx_ino_t fsh_ninodes; /* allocated inodes */ 51 __fs32 fsh_ninodes; /* allocated inodes */
51 u_int32_t fsh_nau; /* number of IAUs */ 52 __fs32 fsh_nau; /* number of IAUs */
52 u_int32_t fsh_old_ilesize; /* old size of ilist */ 53 __fs32 fsh_old_ilesize; /* old size of ilist */
53 u_int32_t fsh_dflags; /* flags */ 54 __fs32 fsh_dflags; /* flags */
54 u_int32_t fsh_quota; /* quota limit */ 55 __fs32 fsh_quota; /* quota limit */
55 vx_ino_t fsh_maxinode; /* maximum inode number */ 56 __fs32 fsh_maxinode; /* maximum inode number */
56 vx_ino_t fsh_iauino; /* IAU inode */ 57 __fs32 fsh_iauino; /* IAU inode */
57 vx_ino_t fsh_ilistino[2]; /* ilist inodes */ 58 __fs32 fsh_ilistino[2]; /* ilist inodes */
58 vx_ino_t fsh_lctino; /* link count table inode */ 59 __fs32 fsh_lctino; /* link count table inode */
59 60
60 /* 61 /*
61 * Slightly more fields follow, but they 62 * Slightly more fields follow, but they
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 3e2ccade61ed..1f41b25ef38b 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -42,9 +43,6 @@
42#include "vxfs_extern.h" 43#include "vxfs_extern.h"
43 44
44 45
45struct kmem_cache *vxfs_inode_cachep;
46
47
48#ifdef DIAGNOSTIC 46#ifdef DIAGNOSTIC
49/* 47/*
50 * Dump inode contents (partially). 48 * Dump inode contents (partially).
@@ -68,6 +66,83 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
68} 66}
69#endif 67#endif
70 68
69/**
70 * vxfs_transmod - mode for a VxFS inode
71 * @vip: VxFS inode
72 *
73 * Description:
74 * vxfs_transmod returns a Linux mode_t for a given
75 * VxFS inode structure.
76 */
77static __inline__ umode_t
78vxfs_transmod(struct vxfs_inode_info *vip)
79{
80 umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
81
82 if (VXFS_ISFIFO(vip))
83 ret |= S_IFIFO;
84 if (VXFS_ISCHR(vip))
85 ret |= S_IFCHR;
86 if (VXFS_ISDIR(vip))
87 ret |= S_IFDIR;
88 if (VXFS_ISBLK(vip))
89 ret |= S_IFBLK;
90 if (VXFS_ISLNK(vip))
91 ret |= S_IFLNK;
92 if (VXFS_ISREG(vip))
93 ret |= S_IFREG;
94 if (VXFS_ISSOC(vip))
95 ret |= S_IFSOCK;
96
97 return (ret);
98}
99
100static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
101 struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
102{
103 struct inode *inode = &vip->vfs_inode;
104
105 vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode);
106 vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink);
107 vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid);
108 vip->vii_gid = fs32_to_cpu(sbi, dip->vdi_gid);
109 vip->vii_size = fs64_to_cpu(sbi, dip->vdi_size);
110 vip->vii_atime = fs32_to_cpu(sbi, dip->vdi_atime);
111 vip->vii_autime = fs32_to_cpu(sbi, dip->vdi_autime);
112 vip->vii_mtime = fs32_to_cpu(sbi, dip->vdi_mtime);
113 vip->vii_mutime = fs32_to_cpu(sbi, dip->vdi_mutime);
114 vip->vii_ctime = fs32_to_cpu(sbi, dip->vdi_ctime);
115 vip->vii_cutime = fs32_to_cpu(sbi, dip->vdi_cutime);
116 vip->vii_orgtype = dip->vdi_orgtype;
117
118 vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks);
119 vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen);
120
121 if (VXFS_ISDIR(vip))
122 vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot);
123 else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip))
124 vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev);
125
126 /* don't endian swap the fields that differ by orgtype */
127 memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org));
128
129 inode->i_mode = vxfs_transmod(vip);
130 i_uid_write(inode, (uid_t)vip->vii_uid);
131 i_gid_write(inode, (gid_t)vip->vii_gid);
132
133 set_nlink(inode, vip->vii_nlink);
134 inode->i_size = vip->vii_size;
135
136 inode->i_atime.tv_sec = vip->vii_atime;
137 inode->i_ctime.tv_sec = vip->vii_ctime;
138 inode->i_mtime.tv_sec = vip->vii_mtime;
139 inode->i_atime.tv_nsec = 0;
140 inode->i_ctime.tv_nsec = 0;
141 inode->i_mtime.tv_nsec = 0;
142
143 inode->i_blocks = vip->vii_blocks;
144 inode->i_generation = vip->vii_gen;
145}
71 146
72/** 147/**
73 * vxfs_blkiget - find inode based on extent # 148 * vxfs_blkiget - find inode based on extent #
@@ -85,50 +160,55 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
85 * buffercache. This function should not be used outside the 160 * buffercache. This function should not be used outside the
86 * read_super() method, otherwise the data may be incoherent. 161 * read_super() method, otherwise the data may be incoherent.
87 */ 162 */
88struct vxfs_inode_info * 163struct inode *
89vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) 164vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
90{ 165{
91 struct buffer_head *bp; 166 struct buffer_head *bp;
167 struct inode *inode;
92 u_long block, offset; 168 u_long block, offset;
93 169
170 inode = new_inode(sbp);
171 if (!inode)
172 return NULL;
173 inode->i_ino = get_next_ino();
174
94 block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); 175 block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
95 offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); 176 offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
96 bp = sb_bread(sbp, block); 177 bp = sb_bread(sbp, block);
97 178
98 if (bp && buffer_mapped(bp)) { 179 if (bp && buffer_mapped(bp)) {
99 struct vxfs_inode_info *vip; 180 struct vxfs_inode_info *vip = VXFS_INO(inode);
100 struct vxfs_dinode *dip; 181 struct vxfs_dinode *dip;
101 182
102 if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
103 goto fail;
104 dip = (struct vxfs_dinode *)(bp->b_data + offset); 183 dip = (struct vxfs_dinode *)(bp->b_data + offset);
105 memcpy(vip, dip, sizeof(*vip)); 184 dip2vip_cpy(VXFS_SBI(sbp), vip, dip);
185 vip->vfs_inode.i_mapping->a_ops = &vxfs_aops;
106#ifdef DIAGNOSTIC 186#ifdef DIAGNOSTIC
107 vxfs_dumpi(vip, ino); 187 vxfs_dumpi(vip, ino);
108#endif 188#endif
109 brelse(bp); 189 brelse(bp);
110 return (vip); 190 return inode;
111 } 191 }
112 192
113fail:
114 printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); 193 printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
115 brelse(bp); 194 brelse(bp);
195 iput(inode);
116 return NULL; 196 return NULL;
117} 197}
118 198
119/** 199/**
120 * __vxfs_iget - generic find inode facility 200 * __vxfs_iget - generic find inode facility
121 * @sbp: VFS superblock
122 * @ino: inode number
123 * @ilistp: inode list 201 * @ilistp: inode list
202 * @vip: VxFS inode to fill in
203 * @ino: inode number
124 * 204 *
125 * Description: 205 * Description:
126 * Search the for inode number @ino in the filesystem 206 * Search the for inode number @ino in the filesystem
127 * described by @sbp. Use the specified inode table (@ilistp). 207 * described by @sbp. Use the specified inode table (@ilistp).
128 * Returns the matching VxFS inode on success, else an error code. 208 * Returns the matching inode on success, else an error code.
129 */ 209 */
130static struct vxfs_inode_info * 210static int
131__vxfs_iget(ino_t ino, struct inode *ilistp) 211__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino)
132{ 212{
133 struct page *pp; 213 struct page *pp;
134 u_long offset; 214 u_long offset;
@@ -137,28 +217,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
137 pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); 217 pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
138 218
139 if (!IS_ERR(pp)) { 219 if (!IS_ERR(pp)) {
140 struct vxfs_inode_info *vip;
141 struct vxfs_dinode *dip; 220 struct vxfs_dinode *dip;
142 caddr_t kaddr = (char *)page_address(pp); 221 caddr_t kaddr = (char *)page_address(pp);
143 222
144 if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
145 goto fail;
146 dip = (struct vxfs_dinode *)(kaddr + offset); 223 dip = (struct vxfs_dinode *)(kaddr + offset);
147 memcpy(vip, dip, sizeof(*vip)); 224 dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip);
225 vip->vfs_inode.i_mapping->a_ops = &vxfs_aops;
148#ifdef DIAGNOSTIC 226#ifdef DIAGNOSTIC
149 vxfs_dumpi(vip, ino); 227 vxfs_dumpi(vip, ino);
150#endif 228#endif
151 vxfs_put_page(pp); 229 vxfs_put_page(pp);
152 return (vip); 230 return 0;
153 } 231 }
154 232
155 printk(KERN_WARNING "vxfs: error on page %p\n", pp); 233 printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n",
156 return ERR_CAST(pp); 234 pp, (unsigned long)ino);
157 235 return PTR_ERR(pp);
158fail:
159 printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
160 vxfs_put_page(pp);
161 return ERR_PTR(-ENOMEM);
162} 236}
163 237
164/** 238/**
@@ -169,116 +243,26 @@ fail:
169 * Description: 243 * Description:
170 * Find inode @ino in the filesystem described by @sbp using 244 * Find inode @ino in the filesystem described by @sbp using
171 * the structural inode list. 245 * the structural inode list.
172 * Returns the matching VxFS inode on success, else a NULL pointer. 246 * Returns the matching inode on success, else a NULL pointer.
173 */
174struct vxfs_inode_info *
175vxfs_stiget(struct super_block *sbp, ino_t ino)
176{
177 struct vxfs_inode_info *vip;
178
179 vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
180 return IS_ERR(vip) ? NULL : vip;
181}
182
183/**
184 * vxfs_transmod - mode for a VxFS inode
185 * @vip: VxFS inode
186 *
187 * Description:
188 * vxfs_transmod returns a Linux mode_t for a given
189 * VxFS inode structure.
190 */
191static __inline__ umode_t
192vxfs_transmod(struct vxfs_inode_info *vip)
193{
194 umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
195
196 if (VXFS_ISFIFO(vip))
197 ret |= S_IFIFO;
198 if (VXFS_ISCHR(vip))
199 ret |= S_IFCHR;
200 if (VXFS_ISDIR(vip))
201 ret |= S_IFDIR;
202 if (VXFS_ISBLK(vip))
203 ret |= S_IFBLK;
204 if (VXFS_ISLNK(vip))
205 ret |= S_IFLNK;
206 if (VXFS_ISREG(vip))
207 ret |= S_IFREG;
208 if (VXFS_ISSOC(vip))
209 ret |= S_IFSOCK;
210
211 return (ret);
212}
213
214/**
215 * vxfs_iinit- helper to fill inode fields
216 * @ip: VFS inode
217 * @vip: VxFS inode
218 *
219 * Description:
220 * vxfs_instino is a helper function to fill in all relevant
221 * fields in @ip from @vip.
222 */
223static void
224vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
225{
226
227 ip->i_mode = vxfs_transmod(vip);
228 i_uid_write(ip, (uid_t)vip->vii_uid);
229 i_gid_write(ip, (gid_t)vip->vii_gid);
230
231 set_nlink(ip, vip->vii_nlink);
232 ip->i_size = vip->vii_size;
233
234 ip->i_atime.tv_sec = vip->vii_atime;
235 ip->i_ctime.tv_sec = vip->vii_ctime;
236 ip->i_mtime.tv_sec = vip->vii_mtime;
237 ip->i_atime.tv_nsec = 0;
238 ip->i_ctime.tv_nsec = 0;
239 ip->i_mtime.tv_nsec = 0;
240
241 ip->i_blocks = vip->vii_blocks;
242 ip->i_generation = vip->vii_gen;
243
244 ip->i_private = vip;
245
246}
247
248/**
249 * vxfs_get_fake_inode - get fake inode structure
250 * @sbp: filesystem superblock
251 * @vip: fspriv inode
252 *
253 * Description:
254 * vxfs_fake_inode gets a fake inode (not in the inode hash) for a
255 * superblock, vxfs_inode pair.
256 * Returns the filled VFS inode.
257 */ 247 */
258struct inode * 248struct inode *
259vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) 249vxfs_stiget(struct super_block *sbp, ino_t ino)
260{ 250{
261 struct inode *ip = NULL; 251 struct inode *inode;
262 252 int error;
263 if ((ip = new_inode(sbp))) { 253
264 ip->i_ino = get_next_ino(); 254 inode = new_inode(sbp);
265 vxfs_iinit(ip, vip); 255 if (!inode)
266 ip->i_mapping->a_ops = &vxfs_aops; 256 return NULL;
257 inode->i_ino = get_next_ino();
258
259 error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino);
260 if (error) {
261 iput(inode);
262 return NULL;
267 } 263 }
268 return (ip);
269}
270 264
271/** 265 return inode;
272 * vxfs_put_fake_inode - free faked inode
273 * *ip: VFS inode
274 *
275 * Description:
276 * vxfs_put_fake_inode frees all data associated with @ip.
277 */
278void
279vxfs_put_fake_inode(struct inode *ip)
280{
281 iput(ip);
282} 266}
283 267
284/** 268/**
@@ -296,6 +280,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
296 struct vxfs_inode_info *vip; 280 struct vxfs_inode_info *vip;
297 const struct address_space_operations *aops; 281 const struct address_space_operations *aops;
298 struct inode *ip; 282 struct inode *ip;
283 int error;
299 284
300 ip = iget_locked(sbp, ino); 285 ip = iget_locked(sbp, ino);
301 if (!ip) 286 if (!ip)
@@ -303,14 +288,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
303 if (!(ip->i_state & I_NEW)) 288 if (!(ip->i_state & I_NEW))
304 return ip; 289 return ip;
305 290
306 vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist); 291 vip = VXFS_INO(ip);
307 if (IS_ERR(vip)) { 292 error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino);
293 if (error) {
308 iget_failed(ip); 294 iget_failed(ip);
309 return ERR_CAST(vip); 295 return ERR_PTR(error);
310 } 296 }
311 297
312 vxfs_iinit(ip, vip);
313
314 if (VXFS_ISIMMED(vip)) 298 if (VXFS_ISIMMED(vip))
315 aops = &vxfs_immed_aops; 299 aops = &vxfs_immed_aops;
316 else 300 else
@@ -341,12 +325,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
341 return ip; 325 return ip;
342} 326}
343 327
344static void vxfs_i_callback(struct rcu_head *head)
345{
346 struct inode *inode = container_of(head, struct inode, i_rcu);
347 kmem_cache_free(vxfs_inode_cachep, inode->i_private);
348}
349
350/** 328/**
351 * vxfs_evict_inode - remove inode from main memory 329 * vxfs_evict_inode - remove inode from main memory
352 * @ip: inode to discard. 330 * @ip: inode to discard.
@@ -360,5 +338,4 @@ vxfs_evict_inode(struct inode *ip)
360{ 338{
361 truncate_inode_pages_final(&ip->i_data); 339 truncate_inode_pages_final(&ip->i_data);
362 clear_inode(ip); 340 clear_inode(ip);
363 call_rcu(&ip->i_rcu, vxfs_i_callback);
364} 341}
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb11263f..f012abed125d 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -66,74 +67,74 @@ enum {
66 * Data stored immediately in the inode. 67 * Data stored immediately in the inode.
67 */ 68 */
68struct vxfs_immed { 69struct vxfs_immed {
69 u_int8_t vi_immed[VXFS_NIMMED]; 70 __u8 vi_immed[VXFS_NIMMED];
70}; 71};
71 72
72struct vxfs_ext4 { 73struct vxfs_ext4 {
73 u_int32_t ve4_spare; /* ?? */ 74 __fs32 ve4_spare; /* ?? */
74 u_int32_t ve4_indsize; /* Indirect extent size */ 75 __fs32 ve4_indsize; /* Indirect extent size */
75 vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ 76 __fs32 ve4_indir[VXFS_NIADDR]; /* Indirect extents */
76 struct direct { /* Direct extents */ 77 struct direct { /* Direct extents */
77 vx_daddr_t extent; /* Extent number */ 78 __fs32 extent; /* Extent number */
78 int32_t size; /* Size of extent */ 79 __fs32 size; /* Size of extent */
79 } ve4_direct[VXFS_NDADDR]; 80 } ve4_direct[VXFS_NDADDR];
80}; 81};
81 82
82struct vxfs_typed { 83struct vxfs_typed {
83 u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ 84 __fs64 vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
84 vx_daddr_t vt_block; /* Extent block */ 85 __fs32 vt_block; /* Extent block */
85 int32_t vt_size; /* Size in blocks */ 86 __fs32 vt_size; /* Size in blocks */
86}; 87};
87 88
88struct vxfs_typed_dev4 { 89struct vxfs_typed_dev4 {
89 u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ 90 __fs64 vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
90 u_int64_t vd4_block; /* Extent block */ 91 __fs64 vd4_block; /* Extent block */
91 u_int64_t vd4_size; /* Size in blocks */ 92 __fs64 vd4_size; /* Size in blocks */
92 int32_t vd4_dev; /* Device ID */ 93 __fs32 vd4_dev; /* Device ID */
93 u_int32_t __pad1; 94 __u8 __pad1;
94}; 95};
95 96
96/* 97/*
97 * The inode as contained on the physical device. 98 * The inode as contained on the physical device.
98 */ 99 */
99struct vxfs_dinode { 100struct vxfs_dinode {
100 int32_t vdi_mode; 101 __fs32 vdi_mode;
101 u_int32_t vdi_nlink; /* Link count */ 102 __fs32 vdi_nlink; /* Link count */
102 u_int32_t vdi_uid; /* UID */ 103 __fs32 vdi_uid; /* UID */
103 u_int32_t vdi_gid; /* GID */ 104 __fs32 vdi_gid; /* GID */
104 u_int64_t vdi_size; /* Inode size in bytes */ 105 __fs64 vdi_size; /* Inode size in bytes */
105 u_int32_t vdi_atime; /* Last time accessed - sec */ 106 __fs32 vdi_atime; /* Last time accessed - sec */
106 u_int32_t vdi_autime; /* Last time accessed - usec */ 107 __fs32 vdi_autime; /* Last time accessed - usec */
107 u_int32_t vdi_mtime; /* Last modify time - sec */ 108 __fs32 vdi_mtime; /* Last modify time - sec */
108 u_int32_t vdi_mutime; /* Last modify time - usec */ 109 __fs32 vdi_mutime; /* Last modify time - usec */
109 u_int32_t vdi_ctime; /* Create time - sec */ 110 __fs32 vdi_ctime; /* Create time - sec */
110 u_int32_t vdi_cutime; /* Create time - usec */ 111 __fs32 vdi_cutime; /* Create time - usec */
111 u_int8_t vdi_aflags; /* Allocation flags */ 112 __u8 vdi_aflags; /* Allocation flags */
112 u_int8_t vdi_orgtype; /* Organisation type */ 113 __u8 vdi_orgtype; /* Organisation type */
113 u_int16_t vdi_eopflags; 114 __fs16 vdi_eopflags;
114 u_int32_t vdi_eopdata; 115 __fs32 vdi_eopdata;
115 union { 116 union {
116 u_int32_t rdev; 117 __fs32 rdev;
117 u_int32_t dotdot; 118 __fs32 dotdot;
118 struct { 119 struct {
119 u_int32_t reserved; 120 __u32 reserved;
120 u_int32_t fixextsize; 121 __fs32 fixextsize;
121 } i_regular; 122 } i_regular;
122 struct { 123 struct {
123 u_int32_t matchino; 124 __fs32 matchino;
124 u_int32_t fsetindex; 125 __fs32 fsetindex;
125 } i_vxspec; 126 } i_vxspec;
126 u_int64_t align; 127 __u64 align;
127 } vdi_ftarea; 128 } vdi_ftarea;
128 u_int32_t vdi_blocks; /* How much blocks does inode occupy */ 129 __fs32 vdi_blocks; /* How much blocks does inode occupy */
129 u_int32_t vdi_gen; /* Inode generation */ 130 __fs32 vdi_gen; /* Inode generation */
130 u_int64_t vdi_version; /* Version */ 131 __fs64 vdi_version; /* Version */
131 union { 132 union {
132 struct vxfs_immed immed; 133 struct vxfs_immed immed;
133 struct vxfs_ext4 ext4; 134 struct vxfs_ext4 ext4;
134 struct vxfs_typed typed[VXFS_NTYPED]; 135 struct vxfs_typed typed[VXFS_NTYPED];
135 } vdi_org; 136 } vdi_org;
136 u_int32_t vdi_iattrino; 137 __fs32 vdi_iattrino;
137}; 138};
138 139
139#define vdi_rdev vdi_ftarea.rdev 140#define vdi_rdev vdi_ftarea.rdev
@@ -149,32 +150,45 @@ struct vxfs_dinode {
149 150
150/* 151/*
151 * The inode as represented in the main memory. 152 * The inode as represented in the main memory.
152 *
153 * TBD: This should become a separate structure...
154 */ 153 */
155#define vxfs_inode_info vxfs_dinode 154struct vxfs_inode_info {
156 155 struct inode vfs_inode;
157#define vii_mode vdi_mode 156
158#define vii_uid vdi_uid 157 __u32 vii_mode;
159#define vii_gid vdi_gid 158 __u32 vii_nlink; /* Link count */
160#define vii_nlink vdi_nlink 159 __u32 vii_uid; /* UID */
161#define vii_size vdi_size 160 __u32 vii_gid; /* GID */
162#define vii_atime vdi_atime 161 __u64 vii_size; /* Inode size in bytes */
163#define vii_ctime vdi_ctime 162 __u32 vii_atime; /* Last time accessed - sec */
164#define vii_mtime vdi_mtime 163 __u32 vii_autime; /* Last time accessed - usec */
165#define vii_blocks vdi_blocks 164 __u32 vii_mtime; /* Last modify time - sec */
166#define vii_org vdi_org 165 __u32 vii_mutime; /* Last modify time - usec */
167#define vii_orgtype vdi_orgtype 166 __u32 vii_ctime; /* Create time - sec */
168#define vii_gen vdi_gen 167 __u32 vii_cutime; /* Create time - usec */
169 168 __u8 vii_orgtype; /* Organisation type */
170#define vii_rdev vdi_ftarea.rdev 169 union {
171#define vii_dotdot vdi_ftarea.dotdot 170 __u32 rdev;
172#define vii_fixextsize vdi_ftarea.regular.fixextsize 171 __u32 dotdot;
173#define vii_matchino vdi_ftarea.vxspec.matchino 172 } vii_ftarea;
174#define vii_fsetindex vdi_ftarea.vxspec.fsetindex 173 __u32 vii_blocks; /* How much blocks does inode occupy */
175 174 __u32 vii_gen; /* Inode generation */
176#define vii_immed vdi_org.immed 175 union {
177#define vii_ext4 vdi_org.ext4 176 struct vxfs_immed immed;
178#define vii_typed vdi_org.typed 177 struct vxfs_ext4 ext4;
178 struct vxfs_typed typed[VXFS_NTYPED];
179 } vii_org;
180};
181
182#define vii_rdev vii_ftarea.rdev
183#define vii_dotdot vii_ftarea.dotdot
184
185#define vii_immed vii_org.immed
186#define vii_ext4 vii_org.ext4
187#define vii_typed vii_org.typed
188
189static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode)
190{
191 return container_of(inode, struct vxfs_inode_info, vfs_inode);
192}
179 193
180#endif /* _VXFS_INODE_H_ */ 194#endif /* _VXFS_INODE_H_ */
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 6d576b97f2c8..ce4785fd81c6 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -61,33 +62,6 @@ const struct file_operations vxfs_dir_operations = {
61 .iterate_shared = vxfs_readdir, 62 .iterate_shared = vxfs_readdir,
62}; 63};
63 64
64static inline u_long
65dir_blocks(struct inode *ip)
66{
67 u_long bsize = ip->i_sb->s_blocksize;
68 return (ip->i_size + bsize - 1) & ~(bsize - 1);
69}
70
71/*
72 * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
73 *
74 * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
75 */
76static inline int
77vxfs_match(int len, const char * const name, struct vxfs_direct *de)
78{
79 if (len != de->d_namelen)
80 return 0;
81 if (!de->d_ino)
82 return 0;
83 return !memcmp(name, de->d_name, len);
84}
85
86static inline struct vxfs_direct *
87vxfs_next_entry(struct vxfs_direct *de)
88{
89 return ((struct vxfs_direct *)((char*)de + de->d_reclen));
90}
91 65
92/** 66/**
93 * vxfs_find_entry - find a mathing directory entry for a dentry 67 * vxfs_find_entry - find a mathing directory entry for a dentry
@@ -106,50 +80,64 @@ vxfs_next_entry(struct vxfs_direct *de)
106static struct vxfs_direct * 80static struct vxfs_direct *
107vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) 81vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
108{ 82{
109 u_long npages, page, nblocks, pblocks, block; 83 u_long bsize = ip->i_sb->s_blocksize;
110 u_long bsize = ip->i_sb->s_blocksize; 84 const char *name = dp->d_name.name;
111 const char *name = dp->d_name.name; 85 int namelen = dp->d_name.len;
112 int namelen = dp->d_name.len; 86 loff_t limit = VXFS_DIRROUND(ip->i_size);
113 87 struct vxfs_direct *de_exit = NULL;
114 npages = dir_pages(ip); 88 loff_t pos = 0;
115 nblocks = dir_blocks(ip); 89 struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
116 pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
117
118 for (page = 0; page < npages; page++) {
119 caddr_t kaddr;
120 struct page *pp;
121 90
122 pp = vxfs_get_page(ip->i_mapping, page); 91 while (pos < limit) {
92 struct page *pp;
93 char *kaddr;
94 int pg_ofs = pos & ~PAGE_MASK;
95
96 pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
123 if (IS_ERR(pp)) 97 if (IS_ERR(pp))
124 continue; 98 return NULL;
125 kaddr = (caddr_t)page_address(pp); 99 kaddr = (char *)page_address(pp);
126 100
127 for (block = 0; block <= nblocks && block <= pblocks; block++) { 101 while (pg_ofs < PAGE_SIZE && pos < limit) {
128 caddr_t baddr, limit; 102 struct vxfs_direct *de;
129 struct vxfs_dirblk *dbp; 103
130 struct vxfs_direct *de; 104 if ((pos & (bsize - 1)) < 4) {
131 105 struct vxfs_dirblk *dbp =
132 baddr = kaddr + (block * bsize); 106 (struct vxfs_dirblk *)
133 limit = baddr + bsize - VXFS_DIRLEN(1); 107 (kaddr + (pos & ~PAGE_MASK));
134 108 int overhead = VXFS_DIRBLKOV(sbi, dbp);
135 dbp = (struct vxfs_dirblk *)baddr; 109
136 de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp)); 110 pos += overhead;
137 111 pg_ofs += overhead;
138 for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { 112 }
139 if (!de->d_reclen) 113 de = (struct vxfs_direct *)(kaddr + pg_ofs);
140 break; 114
141 if (!de->d_ino) 115 if (!de->d_reclen) {
142 continue; 116 pos += bsize - 1;
143 if (vxfs_match(namelen, name, de)) { 117 pos &= ~(bsize - 1);
144 *ppp = pp; 118 break;
145 return (de); 119 }
146 } 120
121 pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
122 pos += fs16_to_cpu(sbi, de->d_reclen);
123 if (!de->d_ino)
124 continue;
125
126 if (namelen != fs16_to_cpu(sbi, de->d_namelen))
127 continue;
128 if (!memcmp(name, de->d_name, namelen)) {
129 *ppp = pp;
130 de_exit = de;
131 break;
147 } 132 }
148 } 133 }
149 vxfs_put_page(pp); 134 if (!de_exit)
135 vxfs_put_page(pp);
136 else
137 break;
150 } 138 }
151 139
152 return NULL; 140 return de_exit;
153} 141}
154 142
155/** 143/**
@@ -173,7 +161,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
173 161
174 de = vxfs_find_entry(dip, dp, &pp); 162 de = vxfs_find_entry(dip, dp, &pp);
175 if (de) { 163 if (de) {
176 ino = de->d_ino; 164 ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
177 kunmap(pp); 165 kunmap(pp);
178 put_page(pp); 166 put_page(pp);
179 } 167 }
@@ -233,74 +221,80 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
233 struct inode *ip = file_inode(fp); 221 struct inode *ip = file_inode(fp);
234 struct super_block *sbp = ip->i_sb; 222 struct super_block *sbp = ip->i_sb;
235 u_long bsize = sbp->s_blocksize; 223 u_long bsize = sbp->s_blocksize;
236 u_long page, npages, block, pblocks, nblocks, offset; 224 loff_t pos, limit;
237 loff_t pos; 225 struct vxfs_sb_info *sbi = VXFS_SBI(sbp);
238 226
239 if (ctx->pos == 0) { 227 if (ctx->pos == 0) {
240 if (!dir_emit_dot(fp, ctx)) 228 if (!dir_emit_dot(fp, ctx))
241 return 0; 229 goto out;
242 ctx->pos = 1; 230 ctx->pos++;
243 } 231 }
244 if (ctx->pos == 1) { 232 if (ctx->pos == 1) {
245 if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR)) 233 if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
246 return 0; 234 goto out;
247 ctx->pos = 2; 235 ctx->pos++;
248 } 236 }
249 pos = ctx->pos - 2;
250
251 if (pos > VXFS_DIRROUND(ip->i_size))
252 return 0;
253 237
254 npages = dir_pages(ip); 238 limit = VXFS_DIRROUND(ip->i_size);
255 nblocks = dir_blocks(ip); 239 if (ctx->pos > limit)
256 pblocks = VXFS_BLOCK_PER_PAGE(sbp); 240 goto out;
257 241
258 page = pos >> PAGE_SHIFT; 242 pos = ctx->pos & ~3L;
259 offset = pos & ~PAGE_MASK;
260 block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
261 243
262 for (; page < npages; page++, block = 0) { 244 while (pos < limit) {
263 char *kaddr; 245 struct page *pp;
264 struct page *pp; 246 char *kaddr;
247 int pg_ofs = pos & ~PAGE_MASK;
248 int rc = 0;
265 249
266 pp = vxfs_get_page(ip->i_mapping, page); 250 pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
267 if (IS_ERR(pp)) 251 if (IS_ERR(pp))
268 continue; 252 return -ENOMEM;
253
269 kaddr = (char *)page_address(pp); 254 kaddr = (char *)page_address(pp);
270 255
271 for (; block <= nblocks && block <= pblocks; block++) { 256 while (pg_ofs < PAGE_SIZE && pos < limit) {
272 char *baddr, *limit; 257 struct vxfs_direct *de;
273 struct vxfs_dirblk *dbp;
274 struct vxfs_direct *de;
275 258
276 baddr = kaddr + (block * bsize); 259 if ((pos & (bsize - 1)) < 4) {
277 limit = baddr + bsize - VXFS_DIRLEN(1); 260 struct vxfs_dirblk *dbp =
278 261 (struct vxfs_dirblk *)
279 dbp = (struct vxfs_dirblk *)baddr; 262 (kaddr + (pos & ~PAGE_MASK));
280 de = (struct vxfs_direct *) 263 int overhead = VXFS_DIRBLKOV(sbi, dbp);
281 (offset ? 264
282 (kaddr + offset) : 265 pos += overhead;
283 (baddr + VXFS_DIRBLKOV(dbp))); 266 pg_ofs += overhead;
284 267 }
285 for (; (char *)de <= limit; de = vxfs_next_entry(de)) { 268 de = (struct vxfs_direct *)(kaddr + pg_ofs);
286 if (!de->d_reclen) 269
287 break; 270 if (!de->d_reclen) {
288 if (!de->d_ino) 271 pos += bsize - 1;
289 continue; 272 pos &= ~(bsize - 1);
290 273 break;
291 offset = (char *)de - kaddr; 274 }
292 ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; 275
293 if (!dir_emit(ctx, de->d_name, de->d_namelen, 276 pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
294 de->d_ino, DT_UNKNOWN)) { 277 pos += fs16_to_cpu(sbi, de->d_reclen);
295 vxfs_put_page(pp); 278 if (!de->d_ino)
296 return 0; 279 continue;
297 } 280
281 rc = dir_emit(ctx, de->d_name,
282 fs16_to_cpu(sbi, de->d_namelen),
283 fs32_to_cpu(sbi, de->d_ino),
284 DT_UNKNOWN);
285 if (!rc) {
286 /* the dir entry was not read, fix pos. */
287 pos -= fs16_to_cpu(sbi, de->d_reclen);
288 break;
298 } 289 }
299 offset = 0;
300 } 290 }
301 vxfs_put_page(pp); 291 vxfs_put_page(pp);
302 offset = 0; 292 if (!rc)
293 break;
303 } 294 }
304 ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; 295
296 ctx->pos = pos | 2;
297
298out:
305 return 0; 299 return 0;
306} 300}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 049500847903..813da6685151 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -43,14 +43,14 @@ static inline void
43vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) 43vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
44{ 44{
45 BUG_ON(infp->vsi_fshino); 45 BUG_ON(infp->vsi_fshino);
46 infp->vsi_fshino = fshp->olt_fsino[0]; 46 infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);
47} 47}
48 48
49static inline void 49static inline void
50vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) 50vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
51{ 51{
52 BUG_ON(infp->vsi_iext); 52 BUG_ON(infp->vsi_iext);
53 infp->vsi_iext = ilistp->olt_iext[0]; 53 infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);
54} 54}
55 55
56static inline u_long 56static inline u_long
@@ -81,13 +81,12 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
81 struct vxfs_olt *op; 81 struct vxfs_olt *op;
82 char *oaddr, *eaddr; 82 char *oaddr, *eaddr;
83 83
84
85 bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize)); 84 bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
86 if (!bp || !bp->b_data) 85 if (!bp || !bp->b_data)
87 goto fail; 86 goto fail;
88 87
89 op = (struct vxfs_olt *)bp->b_data; 88 op = (struct vxfs_olt *)bp->b_data;
90 if (op->olt_magic != VXFS_OLT_MAGIC) { 89 if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {
91 printk(KERN_NOTICE "vxfs: ivalid olt magic number\n"); 90 printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
92 goto fail; 91 goto fail;
93 } 92 }
@@ -102,14 +101,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
102 goto fail; 101 goto fail;
103 } 102 }
104 103
105 oaddr = bp->b_data + op->olt_size; 104 oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
106 eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize); 105 eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
107 106
108 while (oaddr < eaddr) { 107 while (oaddr < eaddr) {
109 struct vxfs_oltcommon *ocp = 108 struct vxfs_oltcommon *ocp =
110 (struct vxfs_oltcommon *)oaddr; 109 (struct vxfs_oltcommon *)oaddr;
111 110
112 switch (ocp->olt_type) { 111 switch (fs32_to_cpu(infp, ocp->olt_type)) {
113 case VXFS_OLT_FSHEAD: 112 case VXFS_OLT_FSHEAD:
114 vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp); 113 vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
115 break; 114 break;
@@ -118,11 +117,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
118 break; 117 break;
119 } 118 }
120 119
121 oaddr += ocp->olt_size; 120 oaddr += fs32_to_cpu(infp, ocp->olt_size);
122 } 121 }
123 122
124 brelse(bp); 123 brelse(bp);
125 return 0; 124 return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
126 125
127fail: 126fail:
128 brelse(bp); 127 brelse(bp);
diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h
index b7b3af502615..0c0b0c9fa557 100644
--- a/fs/freevxfs/vxfs_olt.h
+++ b/fs/freevxfs/vxfs_olt.h
@@ -63,83 +63,83 @@ enum {
63 * the initial inode list, the fileset header or the device configuration. 63 * the initial inode list, the fileset header or the device configuration.
64 */ 64 */
65struct vxfs_olt { 65struct vxfs_olt {
66 u_int32_t olt_magic; /* magic number */ 66 __fs32 olt_magic; /* magic number */
67 u_int32_t olt_size; /* size of this entry */ 67 __fs32 olt_size; /* size of this entry */
68 u_int32_t olt_checksum; /* checksum of extent */ 68 __fs32 olt_checksum; /* checksum of extent */
69 u_int32_t __unused1; /* ??? */ 69 __u32 __unused1; /* ??? */
70 u_int32_t olt_mtime; /* time of last mod. (sec) */ 70 __fs32 olt_mtime; /* time of last mod. (sec) */
71 u_int32_t olt_mutime; /* time of last mod. (usec) */ 71 __fs32 olt_mutime; /* time of last mod. (usec) */
72 u_int32_t olt_totfree; /* free space in OLT extent */ 72 __fs32 olt_totfree; /* free space in OLT extent */
73 vx_daddr_t olt_extents[2]; /* addr of this extent, replica */ 73 __fs32 olt_extents[2]; /* addr of this extent, replica */
74 u_int32_t olt_esize; /* size of this extent */ 74 __fs32 olt_esize; /* size of this extent */
75 vx_daddr_t olt_next[2]; /* addr of next extent, replica */ 75 __fs32 olt_next[2]; /* addr of next extent, replica */
76 u_int32_t olt_nsize; /* size of next extent */ 76 __fs32 olt_nsize; /* size of next extent */
77 u_int32_t __unused2; /* align to 8 byte boundary */ 77 __u32 __unused2; /* align to 8 byte boundary */
78}; 78};
79 79
80/* 80/*
81 * VxFS common OLT entry (on disk). 81 * VxFS common OLT entry (on disk).
82 */ 82 */
83struct vxfs_oltcommon { 83struct vxfs_oltcommon {
84 u_int32_t olt_type; /* type of this record */ 84 __fs32 olt_type; /* type of this record */
85 u_int32_t olt_size; /* size of this record */ 85 __fs32 olt_size; /* size of this record */
86}; 86};
87 87
88/* 88/*
89 * VxFS free OLT entry (on disk). 89 * VxFS free OLT entry (on disk).
90 */ 90 */
91struct vxfs_oltfree { 91struct vxfs_oltfree {
92 u_int32_t olt_type; /* type of this record */ 92 __fs32 olt_type; /* type of this record */
93 u_int32_t olt_fsize; /* size of this free record */ 93 __fs32 olt_fsize; /* size of this free record */
94}; 94};
95 95
96/* 96/*
97 * VxFS initial-inode list (on disk). 97 * VxFS initial-inode list (on disk).
98 */ 98 */
99struct vxfs_oltilist { 99struct vxfs_oltilist {
100 u_int32_t olt_type; /* type of this record */ 100 __fs32 olt_type; /* type of this record */
101 u_int32_t olt_size; /* size of this record */ 101 __fs32 olt_size; /* size of this record */
102 vx_ino_t olt_iext[2]; /* initial inode list, replica */ 102 __fs32 olt_iext[2]; /* initial inode list, replica */
103}; 103};
104 104
105/* 105/*
106 * Current Usage Table 106 * Current Usage Table
107 */ 107 */
108struct vxfs_oltcut { 108struct vxfs_oltcut {
109 u_int32_t olt_type; /* type of this record */ 109 __fs32 olt_type; /* type of this record */
110 u_int32_t olt_size; /* size of this record */ 110 __fs32 olt_size; /* size of this record */
111 vx_ino_t olt_cutino; /* inode of current usage table */ 111 __fs32 olt_cutino; /* inode of current usage table */
112 u_int32_t __pad; /* unused, 8 byte align */ 112 __u8 __pad; /* unused, 8 byte align */
113}; 113};
114 114
115/* 115/*
116 * Inodes containing Superblock, Intent log and OLTs 116 * Inodes containing Superblock, Intent log and OLTs
117 */ 117 */
118struct vxfs_oltsb { 118struct vxfs_oltsb {
119 u_int32_t olt_type; /* type of this record */ 119 __fs32 olt_type; /* type of this record */
120 u_int32_t olt_size; /* size of this record */ 120 __fs32 olt_size; /* size of this record */
121 vx_ino_t olt_sbino; /* inode of superblock file */ 121 __fs32 olt_sbino; /* inode of superblock file */
122 u_int32_t __unused1; /* ??? */ 122 __u32 __unused1; /* ??? */
123 vx_ino_t olt_logino[2]; /* inode of log file,replica */ 123 __fs32 olt_logino[2]; /* inode of log file,replica */
124 vx_ino_t olt_oltino[2]; /* inode of OLT, replica */ 124 __fs32 olt_oltino[2]; /* inode of OLT, replica */
125}; 125};
126 126
127/* 127/*
128 * Inode containing device configuration + it's replica 128 * Inode containing device configuration + it's replica
129 */ 129 */
130struct vxfs_oltdev { 130struct vxfs_oltdev {
131 u_int32_t olt_type; /* type of this record */ 131 __fs32 olt_type; /* type of this record */
132 u_int32_t olt_size; /* size of this record */ 132 __fs32 olt_size; /* size of this record */
133 vx_ino_t olt_devino[2]; /* inode of device config files */ 133 __fs32 olt_devino[2]; /* inode of device config files */
134}; 134};
135 135
136/* 136/*
137 * Fileset header 137 * Fileset header
138 */ 138 */
139struct vxfs_oltfshead { 139struct vxfs_oltfshead {
140 u_int32_t olt_type; /* type number */ 140 __fs32 olt_type; /* type number */
141 u_int32_t olt_size; /* size of this record */ 141 __fs32 olt_size; /* size of this record */
142 vx_ino_t olt_fsino[2]; /* inodes of fileset header */ 142 __fs32 olt_fsino[2]; /* inodes of fileset header */
143}; 143};
144 144
145#endif /* _VXFS_OLT_H_ */ 145#endif /* _VXFS_OLT_H_ */
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75d50d3..455ce5b77e9b 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001 Christoph Hellwig. 2 * Copyright (c) 2000-2001 Christoph Hellwig.
3 * Copyright (c) 2016 Krzysztof Blaszkowski
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -48,22 +49,11 @@
48#include "vxfs_inode.h" 49#include "vxfs_inode.h"
49 50
50 51
51MODULE_AUTHOR("Christoph Hellwig"); 52MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
52MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); 53MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
53MODULE_LICENSE("Dual BSD/GPL"); 54MODULE_LICENSE("Dual BSD/GPL");
54 55
55 56static struct kmem_cache *vxfs_inode_cachep;
56
57static void vxfs_put_super(struct super_block *);
58static int vxfs_statfs(struct dentry *, struct kstatfs *);
59static int vxfs_remount(struct super_block *, int *, char *);
60
61static const struct super_operations vxfs_super_ops = {
62 .evict_inode = vxfs_evict_inode,
63 .put_super = vxfs_put_super,
64 .statfs = vxfs_statfs,
65 .remount_fs = vxfs_remount,
66};
67 57
68/** 58/**
69 * vxfs_put_super - free superblock resources 59 * vxfs_put_super - free superblock resources
@@ -79,9 +69,9 @@ vxfs_put_super(struct super_block *sbp)
79{ 69{
80 struct vxfs_sb_info *infp = VXFS_SBI(sbp); 70 struct vxfs_sb_info *infp = VXFS_SBI(sbp);
81 71
82 vxfs_put_fake_inode(infp->vsi_fship); 72 iput(infp->vsi_fship);
83 vxfs_put_fake_inode(infp->vsi_ilist); 73 iput(infp->vsi_ilist);
84 vxfs_put_fake_inode(infp->vsi_stilist); 74 iput(infp->vsi_stilist);
85 75
86 brelse(infp->vsi_bp); 76 brelse(infp->vsi_bp);
87 kfree(infp); 77 kfree(infp);
@@ -109,14 +99,15 @@ static int
109vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) 99vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
110{ 100{
111 struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); 101 struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb);
102 struct vxfs_sb *raw_sb = infp->vsi_raw;
112 103
113 bufp->f_type = VXFS_SUPER_MAGIC; 104 bufp->f_type = VXFS_SUPER_MAGIC;
114 bufp->f_bsize = dentry->d_sb->s_blocksize; 105 bufp->f_bsize = dentry->d_sb->s_blocksize;
115 bufp->f_blocks = infp->vsi_raw->vs_dsize; 106 bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
116 bufp->f_bfree = infp->vsi_raw->vs_free; 107 bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
117 bufp->f_bavail = 0; 108 bufp->f_bavail = 0;
118 bufp->f_files = 0; 109 bufp->f_files = 0;
119 bufp->f_ffree = infp->vsi_raw->vs_ifree; 110 bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree);
120 bufp->f_namelen = VXFS_NAMELEN; 111 bufp->f_namelen = VXFS_NAMELEN;
121 112
122 return 0; 113 return 0;
@@ -129,6 +120,81 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
129 return 0; 120 return 0;
130} 121}
131 122
123static struct inode *vxfs_alloc_inode(struct super_block *sb)
124{
125 struct vxfs_inode_info *vi;
126
127 vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
128 if (!vi)
129 return NULL;
130 inode_init_once(&vi->vfs_inode);
131 return &vi->vfs_inode;
132}
133
134static void vxfs_i_callback(struct rcu_head *head)
135{
136 struct inode *inode = container_of(head, struct inode, i_rcu);
137
138 kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode));
139}
140
141static void vxfs_destroy_inode(struct inode *inode)
142{
143 call_rcu(&inode->i_rcu, vxfs_i_callback);
144}
145
146static const struct super_operations vxfs_super_ops = {
147 .alloc_inode = vxfs_alloc_inode,
148 .destroy_inode = vxfs_destroy_inode,
149 .evict_inode = vxfs_evict_inode,
150 .put_super = vxfs_put_super,
151 .statfs = vxfs_statfs,
152 .remount_fs = vxfs_remount,
153};
154
155static int vxfs_try_sb_magic(struct super_block *sbp, int silent,
156 unsigned blk, __fs32 magic)
157{
158 struct buffer_head *bp;
159 struct vxfs_sb *rsbp;
160 struct vxfs_sb_info *infp = VXFS_SBI(sbp);
161 int rc = -ENOMEM;
162
163 bp = sb_bread(sbp, blk);
164 do {
165 if (!bp || !buffer_mapped(bp)) {
166 if (!silent) {
167 printk(KERN_WARNING
168 "vxfs: unable to read disk superblock at %u\n",
169 blk);
170 }
171 break;
172 }
173
174 rc = -EINVAL;
175 rsbp = (struct vxfs_sb *)bp->b_data;
176 if (rsbp->vs_magic != magic) {
177 if (!silent)
178 printk(KERN_NOTICE
179 "vxfs: WRONG superblock magic %08x at %u\n",
180 rsbp->vs_magic, blk);
181 break;
182 }
183
184 rc = 0;
185 infp->vsi_raw = rsbp;
186 infp->vsi_bp = bp;
187 } while (0);
188
189 if (rc) {
190 infp->vsi_raw = NULL;
191 infp->vsi_bp = NULL;
192 brelse(bp);
193 }
194
195 return rc;
196}
197
132/** 198/**
133 * vxfs_read_super - read superblock into memory and initialize filesystem 199 * vxfs_read_super - read superblock into memory and initialize filesystem
134 * @sbp: VFS superblock (to fill) 200 * @sbp: VFS superblock (to fill)
@@ -149,10 +215,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
149{ 215{
150 struct vxfs_sb_info *infp; 216 struct vxfs_sb_info *infp;
151 struct vxfs_sb *rsbp; 217 struct vxfs_sb *rsbp;
152 struct buffer_head *bp = NULL;
153 u_long bsize; 218 u_long bsize;
154 struct inode *root; 219 struct inode *root;
155 int ret = -EINVAL; 220 int ret = -EINVAL;
221 u32 j;
156 222
157 sbp->s_flags |= MS_RDONLY; 223 sbp->s_flags |= MS_RDONLY;
158 224
@@ -168,42 +234,43 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
168 goto out; 234 goto out;
169 } 235 }
170 236
171 bp = sb_bread(sbp, 1); 237 sbp->s_op = &vxfs_super_ops;
172 if (!bp || !buffer_mapped(bp)) { 238 sbp->s_fs_info = infp;
173 if (!silent) {
174 printk(KERN_WARNING
175 "vxfs: unable to read disk superblock\n");
176 }
177 goto out;
178 }
179 239
180 rsbp = (struct vxfs_sb *)bp->b_data; 240 if (!vxfs_try_sb_magic(sbp, silent, 1,
181 if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { 241 (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) {
242 /* Unixware, x86 */
243 infp->byte_order = VXFS_BO_LE;
244 } else if (!vxfs_try_sb_magic(sbp, silent, 8,
245 (__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) {
246 /* HP-UX, parisc */
247 infp->byte_order = VXFS_BO_BE;
248 } else {
182 if (!silent) 249 if (!silent)
183 printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); 250 printk(KERN_NOTICE "vxfs: can't find superblock.\n");
184 goto out; 251 goto out;
185 } 252 }
186 253
187 if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { 254 rsbp = infp->vsi_raw;
188 printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", 255 j = fs32_to_cpu(infp, rsbp->vs_version);
189 rsbp->vs_version); 256 if ((j < 2 || j > 4) && !silent) {
257 printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
190 goto out; 258 goto out;
191 } 259 }
192 260
193#ifdef DIAGNOSTIC 261#ifdef DIAGNOSTIC
194 printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); 262 printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
195 printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); 263 printk(KERN_DEBUG "vxfs: blocksize: %d\n",
264 fs32_to_cpu(infp, rsbp->vs_bsize));
196#endif 265#endif
197 266
198 sbp->s_magic = rsbp->vs_magic; 267 sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
199 sbp->s_fs_info = infp;
200 268
201 infp->vsi_raw = rsbp; 269 infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
202 infp->vsi_bp = bp; 270 infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
203 infp->vsi_oltext = rsbp->vs_oltext[0];
204 infp->vsi_oltsize = rsbp->vs_oltsize;
205 271
206 if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) { 272 j = fs32_to_cpu(infp, rsbp->vs_bsize);
273 if (!sb_set_blocksize(sbp, j)) {
207 printk(KERN_WARNING "vxfs: unable to set final block size\n"); 274 printk(KERN_WARNING "vxfs: unable to set final block size\n");
208 goto out; 275 goto out;
209 } 276 }
@@ -218,7 +285,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
218 goto out; 285 goto out;
219 } 286 }
220 287
221 sbp->s_op = &vxfs_super_ops;
222 root = vxfs_iget(sbp, VXFS_ROOT_INO); 288 root = vxfs_iget(sbp, VXFS_ROOT_INO);
223 if (IS_ERR(root)) { 289 if (IS_ERR(root)) {
224 ret = PTR_ERR(root); 290 ret = PTR_ERR(root);
@@ -233,11 +299,11 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
233 return 0; 299 return 0;
234 300
235out_free_ilist: 301out_free_ilist:
236 vxfs_put_fake_inode(infp->vsi_fship); 302 iput(infp->vsi_fship);
237 vxfs_put_fake_inode(infp->vsi_ilist); 303 iput(infp->vsi_ilist);
238 vxfs_put_fake_inode(infp->vsi_stilist); 304 iput(infp->vsi_stilist);
239out: 305out:
240 brelse(bp); 306 brelse(infp->vsi_bp);
241 kfree(infp); 307 kfree(infp);
242 return ret; 308 return ret;
243} 309}