diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 14:56:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 14:56:29 -0400 |
commit | 0a7736d03720a450727c6ab906e13b60d4d34e42 (patch) | |
tree | c3ddbf0e3dc9ac7273a2cf8d639d83bdf20481d4 | |
parent | a54809f1167243d909b2c63fcd51e1d648deeb01 (diff) | |
parent | bf1bb4b460c8dc3a33793bff21464a9d816697ad (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/Kconfig | 13 | ||||
-rw-r--r-- | fs/freevxfs/vxfs.h | 185 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_bmap.c | 70 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_dir.h | 17 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_extern.h | 10 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_fshead.c | 37 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_fshead.h | 29 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.c | 265 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.h | 146 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_lookup.c | 226 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_olt.c | 15 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_olt.h | 70 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_super.c | 162 |
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 | */ | ||
45 | typedef int32_t vx_daddr_t; | ||
46 | typedef 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 | ||
57 | enum vxfs_byte_order { | ||
58 | VXFS_BO_LE, | ||
59 | VXFS_BO_BE, | ||
60 | }; | ||
61 | |||
62 | typedef __u16 __bitwise __fs16; | ||
63 | typedef __u32 __bitwise __fs32; | ||
64 | typedef __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 | ||
176 | static 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 | |||
184 | static 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 | |||
192 | static 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: | |||
127 | static daddr_t | 130 | static daddr_t |
128 | vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) | 131 | vxfs_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 | |||
201 | vxfs_bmap_typed(struct inode *ip, long iblock) | 210 | vxfs_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 | */ |
50 | struct vxfs_dirblk { | 50 | struct 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 | */ |
65 | struct vxfs_direct { | 65 | struct 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 */ |
54 | extern const struct address_space_operations vxfs_immed_aops; | 54 | extern const struct address_space_operations vxfs_immed_aops; |
55 | extern struct kmem_cache *vxfs_inode_cachep; | ||
56 | extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); | 55 | extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); |
57 | extern struct inode * vxfs_get_fake_inode(struct super_block *, | 56 | extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); |
58 | struct vxfs_inode_info *); | 57 | extern struct inode *vxfs_stiget(struct super_block *, ino_t); |
59 | extern void vxfs_put_fake_inode(struct inode *); | 58 | extern struct inode *vxfs_iget(struct super_block *, ino_t); |
60 | extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); | ||
61 | extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); | ||
62 | extern struct inode * vxfs_iget(struct super_block *, ino_t); | ||
63 | extern void vxfs_evict_inode(struct inode *); | 59 | extern 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 | */ |
44 | struct vxfs_fsh { | 45 | struct 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 | ||
45 | struct 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 | */ | ||
77 | static __inline__ umode_t | ||
78 | vxfs_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 | |||
100 | static 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 | */ |
88 | struct vxfs_inode_info * | 163 | struct inode * |
89 | vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) | 164 | vxfs_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 | ||
113 | fail: | ||
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 | */ |
130 | static struct vxfs_inode_info * | 210 | static 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); | |
158 | fail: | ||
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 | */ | ||
174 | struct vxfs_inode_info * | ||
175 | vxfs_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 | */ | ||
191 | static __inline__ umode_t | ||
192 | vxfs_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 | */ | ||
223 | static void | ||
224 | vxfs_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 | */ |
258 | struct inode * | 248 | struct inode * |
259 | vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) | 249 | vxfs_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 | */ | ||
278 | void | ||
279 | vxfs_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 | ||
344 | static 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 | */ |
68 | struct vxfs_immed { | 69 | struct vxfs_immed { |
69 | u_int8_t vi_immed[VXFS_NIMMED]; | 70 | __u8 vi_immed[VXFS_NIMMED]; |
70 | }; | 71 | }; |
71 | 72 | ||
72 | struct vxfs_ext4 { | 73 | struct 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 | ||
82 | struct vxfs_typed { | 83 | struct 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 | ||
88 | struct vxfs_typed_dev4 { | 89 | struct 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 | */ |
99 | struct vxfs_dinode { | 100 | struct 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 | 154 | struct 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 | |||
189 | static 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 | ||
64 | static inline u_long | ||
65 | dir_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 | */ | ||
76 | static inline int | ||
77 | vxfs_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 | |||
86 | static inline struct vxfs_direct * | ||
87 | vxfs_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) | |||
106 | static struct vxfs_direct * | 80 | static struct vxfs_direct * |
107 | vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) | 81 | vxfs_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 | |||
298 | out: | ||
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 | |||
43 | vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) | 43 | vxfs_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 | ||
49 | static inline void | 49 | static inline void |
50 | vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) | 50 | vxfs_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 | ||
56 | static inline u_long | 56 | static 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 | ||
127 | fail: | 126 | fail: |
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 | */ |
65 | struct vxfs_olt { | 65 | struct 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 | */ |
83 | struct vxfs_oltcommon { | 83 | struct 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 | */ |
91 | struct vxfs_oltfree { | 91 | struct 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 | */ |
99 | struct vxfs_oltilist { | 99 | struct 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 | */ |
108 | struct vxfs_oltcut { | 108 | struct 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 | */ |
118 | struct vxfs_oltsb { | 118 | struct 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 | */ |
130 | struct vxfs_oltdev { | 130 | struct 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 | */ |
139 | struct vxfs_oltfshead { | 139 | struct 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 | ||
51 | MODULE_AUTHOR("Christoph Hellwig"); | 52 | MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski"); |
52 | MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); | 53 | MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); |
53 | MODULE_LICENSE("Dual BSD/GPL"); | 54 | MODULE_LICENSE("Dual BSD/GPL"); |
54 | 55 | ||
55 | 56 | static struct kmem_cache *vxfs_inode_cachep; | |
56 | |||
57 | static void vxfs_put_super(struct super_block *); | ||
58 | static int vxfs_statfs(struct dentry *, struct kstatfs *); | ||
59 | static int vxfs_remount(struct super_block *, int *, char *); | ||
60 | |||
61 | static 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 | |||
109 | vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) | 99 | vxfs_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 | ||
123 | static 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 | |||
134 | static 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 | |||
141 | static void vxfs_destroy_inode(struct inode *inode) | ||
142 | { | ||
143 | call_rcu(&inode->i_rcu, vxfs_i_callback); | ||
144 | } | ||
145 | |||
146 | static 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 | |||
155 | static 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 | ||
235 | out_free_ilist: | 301 | out_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); |
239 | out: | 305 | out: |
240 | brelse(bp); | 306 | brelse(infp->vsi_bp); |
241 | kfree(infp); | 307 | kfree(infp); |
242 | return ret; | 308 | return ret; |
243 | } | 309 | } |