diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 11:56:29 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 11:56:29 -0700 |
commit | 0a7736d03720a450727c6ab906e13b60d4d34e42 (patch) | |
tree | c3ddbf0e3dc9ac7273a2cf8d639d83bdf20481d4 /fs | |
parent | a54809f1167243d909b2c63fcd51e1d648deeb01 (diff) | |
parent | bf1bb4b460c8dc3a33793bff21464a9d816697ad (diff) | |
download | linux-0a7736d03720a450727c6ab906e13b60d4d34e42.tar.bz2 |
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
Diffstat (limited to 'fs')
-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 FreeVxFS is a file system driver that support the VERITAS VxFS(TM) file system format. VERITAS VxFS(TM) is the standard file system of SCO UnixWare (and possibly others) and optionally available - for Sunsoft Solaris, HP-UX and many other operating systems. - Currently only readonly access is supported. + for Sunsoft Solaris, HP-UX and many other operating systems. However + these particular OS implementations of vxfs may differ in on-disk + data endianess and/or superblock offset. The vxfs module has been + tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.) + Currently only readonly access is supported and VxFX versions + 2, 3 and 4. Tests were performed with HP-UX VxFS version 3. NOTE: the file system type as used by mount(1), mount(2) and fstab(5) is 'vxfs' as it describes the file system format, not the actual driver. + There is a userspace utility for HP-UX logical volumes which makes + creating HP-UX logical volumes easy from HP-UX disk block device file + or regular file with image of the disk. See: + https://sourceforge.net/projects/linux-vxfs/ + To compile this as a module, choose M here: the module will be 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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,13 +39,6 @@ */ #include <linux/types.h> - -/* - * Data types for use with the VxFS ondisk format. - */ -typedef int32_t vx_daddr_t; -typedef int32_t vx_ino_t; - /* * Superblock magic number (vxfs_super->vs_magic). */ @@ -60,6 +54,14 @@ typedef int32_t vx_ino_t; */ #define VXFS_NEFREE 32 +enum vxfs_byte_order { + VXFS_BO_LE, + VXFS_BO_BE, +}; + +typedef __u16 __bitwise __fs16; +typedef __u32 __bitwise __fs32; +typedef __u64 __bitwise __fs64; /* * VxFS superblock (disk). @@ -71,83 +73,83 @@ struct vxfs_sb { * Lots of this fields are no more used by version 2 * and never filesystems. */ - u_int32_t vs_magic; /* Magic number */ - int32_t vs_version; /* VxFS version */ - u_int32_t vs_ctime; /* create time - secs */ - u_int32_t vs_cutime; /* create time - usecs */ - int32_t __unused1; /* unused */ - int32_t __unused2; /* unused */ - vx_daddr_t vs_old_logstart; /* obsolete */ - vx_daddr_t vs_old_logend; /* obsolete */ - int32_t vs_bsize; /* block size */ - int32_t vs_size; /* number of blocks */ - int32_t vs_dsize; /* number of data blocks */ - u_int32_t vs_old_ninode; /* obsolete */ - int32_t vs_old_nau; /* obsolete */ - int32_t __unused3; /* unused */ - int32_t vs_old_defiextsize; /* obsolete */ - int32_t vs_old_ilbsize; /* obsolete */ - int32_t vs_immedlen; /* size of immediate data area */ - int32_t vs_ndaddr; /* number of direct extentes */ - vx_daddr_t vs_firstau; /* address of first AU */ - vx_daddr_t vs_emap; /* offset of extent map in AU */ - vx_daddr_t vs_imap; /* offset of inode map in AU */ - vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */ - vx_daddr_t vs_istart; /* offset of inode list in AU */ - vx_daddr_t vs_bstart; /* offset of fdblock in AU */ - vx_daddr_t vs_femap; /* aufirst + emap */ - vx_daddr_t vs_fimap; /* aufirst + imap */ - vx_daddr_t vs_fiextop; /* aufirst + iextop */ - vx_daddr_t vs_fistart; /* aufirst + istart */ - vx_daddr_t vs_fbstart; /* aufirst + bstart */ - int32_t vs_nindir; /* number of entries in indir */ - int32_t vs_aulen; /* length of AU in blocks */ - int32_t vs_auimlen; /* length of imap in blocks */ - int32_t vs_auemlen; /* length of emap in blocks */ - int32_t vs_auilen; /* length of ilist in blocks */ - int32_t vs_aupad; /* length of pad in blocks */ - int32_t vs_aublocks; /* data blocks in AU */ - int32_t vs_maxtier; /* log base 2 of aublocks */ - int32_t vs_inopb; /* number of inodes per blk */ - int32_t vs_old_inopau; /* obsolete */ - int32_t vs_old_inopilb; /* obsolete */ - int32_t vs_old_ndiripau; /* obsolete */ - int32_t vs_iaddrlen; /* size of indirect addr ext. */ - int32_t vs_bshift; /* log base 2 of bsize */ - int32_t vs_inoshift; /* log base 2 of inobp */ - int32_t vs_bmask; /* ~( bsize - 1 ) */ - int32_t vs_boffmask; /* bsize - 1 */ - int32_t vs_old_inomask; /* old_inopilb - 1 */ - int32_t vs_checksum; /* checksum of V1 data */ + __fs32 vs_magic; /* Magic number */ + __fs32 vs_version; /* VxFS version */ + __fs32 vs_ctime; /* create time - secs */ + __fs32 vs_cutime; /* create time - usecs */ + __fs32 __unused1; /* unused */ + __fs32 __unused2; /* unused */ + __fs32 vs_old_logstart; /* obsolete */ + __fs32 vs_old_logend; /* obsolete */ + __fs32 vs_bsize; /* block size */ + __fs32 vs_size; /* number of blocks */ + __fs32 vs_dsize; /* number of data blocks */ + __fs32 vs_old_ninode; /* obsolete */ + __fs32 vs_old_nau; /* obsolete */ + __fs32 __unused3; /* unused */ + __fs32 vs_old_defiextsize; /* obsolete */ + __fs32 vs_old_ilbsize; /* obsolete */ + __fs32 vs_immedlen; /* size of immediate data area */ + __fs32 vs_ndaddr; /* number of direct extentes */ + __fs32 vs_firstau; /* address of first AU */ + __fs32 vs_emap; /* offset of extent map in AU */ + __fs32 vs_imap; /* offset of inode map in AU */ + __fs32 vs_iextop; /* offset of ExtOp. map in AU */ + __fs32 vs_istart; /* offset of inode list in AU */ + __fs32 vs_bstart; /* offset of fdblock in AU */ + __fs32 vs_femap; /* aufirst + emap */ + __fs32 vs_fimap; /* aufirst + imap */ + __fs32 vs_fiextop; /* aufirst + iextop */ + __fs32 vs_fistart; /* aufirst + istart */ + __fs32 vs_fbstart; /* aufirst + bstart */ + __fs32 vs_nindir; /* number of entries in indir */ + __fs32 vs_aulen; /* length of AU in blocks */ + __fs32 vs_auimlen; /* length of imap in blocks */ + __fs32 vs_auemlen; /* length of emap in blocks */ + __fs32 vs_auilen; /* length of ilist in blocks */ + __fs32 vs_aupad; /* length of pad in blocks */ + __fs32 vs_aublocks; /* data blocks in AU */ + __fs32 vs_maxtier; /* log base 2 of aublocks */ + __fs32 vs_inopb; /* number of inodes per blk */ + __fs32 vs_old_inopau; /* obsolete */ + __fs32 vs_old_inopilb; /* obsolete */ + __fs32 vs_old_ndiripau; /* obsolete */ + __fs32 vs_iaddrlen; /* size of indirect addr ext. */ + __fs32 vs_bshift; /* log base 2 of bsize */ + __fs32 vs_inoshift; /* log base 2 of inobp */ + __fs32 vs_bmask; /* ~( bsize - 1 ) */ + __fs32 vs_boffmask; /* bsize - 1 */ + __fs32 vs_old_inomask; /* old_inopilb - 1 */ + __fs32 vs_checksum; /* checksum of V1 data */ /* * Version 1, writable */ - int32_t vs_free; /* number of free blocks */ - int32_t vs_ifree; /* number of free inodes */ - int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */ - int32_t vs_flags; /* flags ?!? */ - u_int8_t vs_mod; /* filesystem has been changed */ - u_int8_t vs_clean; /* clean FS */ - u_int16_t __unused4; /* unused */ - u_int32_t vs_firstlogid; /* mount time log ID */ - u_int32_t vs_wtime; /* last time written - sec */ - u_int32_t vs_wutime; /* last time written - usec */ - u_int8_t vs_fname[6]; /* FS name */ - u_int8_t vs_fpack[6]; /* FS pack name */ - int32_t vs_logversion; /* log format version */ - int32_t __unused5; /* unused */ + __fs32 vs_free; /* number of free blocks */ + __fs32 vs_ifree; /* number of free inodes */ + __fs32 vs_efree[VXFS_NEFREE]; /* number of free extents by size */ + __fs32 vs_flags; /* flags ?!? */ + __u8 vs_mod; /* filesystem has been changed */ + __u8 vs_clean; /* clean FS */ + __fs16 __unused4; /* unused */ + __fs32 vs_firstlogid; /* mount time log ID */ + __fs32 vs_wtime; /* last time written - sec */ + __fs32 vs_wutime; /* last time written - usec */ + __u8 vs_fname[6]; /* FS name */ + __u8 vs_fpack[6]; /* FS pack name */ + __fs32 vs_logversion; /* log format version */ + __u32 __unused5; /* unused */ /* * Version 2, Read-only */ - vx_daddr_t vs_oltext[2]; /* OLT extent and replica */ - int32_t vs_oltsize; /* OLT extent size */ - int32_t vs_iauimlen; /* size of inode map */ - int32_t vs_iausize; /* size of IAU in blocks */ - int32_t vs_dinosize; /* size of inode in bytes */ - int32_t vs_old_dniaddr; /* indir levels per inode */ - int32_t vs_checksum2; /* checksum of V2 RO */ + __fs32 vs_oltext[2]; /* OLT extent and replica */ + __fs32 vs_oltsize; /* OLT extent size */ + __fs32 vs_iauimlen; /* size of inode map */ + __fs32 vs_iausize; /* size of IAU in blocks */ + __fs32 vs_dinosize; /* size of inode in bytes */ + __fs32 vs_old_dniaddr; /* indir levels per inode */ + __fs32 vs_checksum2; /* checksum of V2 RO */ /* * Actually much more... @@ -168,8 +170,32 @@ struct vxfs_sb_info { ino_t vsi_fshino; /* fileset header inode */ daddr_t vsi_oltext; /* OLT extent */ daddr_t vsi_oltsize; /* OLT size */ + enum vxfs_byte_order byte_order; }; +static inline u16 fs16_to_cpu(struct vxfs_sb_info *sbi, __fs16 a) +{ + if (sbi->byte_order == VXFS_BO_BE) + return be16_to_cpu((__force __be16)a); + else + return le16_to_cpu((__force __le16)a); +} + +static inline u32 fs32_to_cpu(struct vxfs_sb_info *sbi, __fs32 a) +{ + if (sbi->byte_order == VXFS_BO_BE) + return be32_to_cpu((__force __be32)a); + else + return le32_to_cpu((__force __le32)a); +} + +static inline u64 fs64_to_cpu(struct vxfs_sb_info *sbi, __fs64 a) +{ + if (sbi->byte_order == VXFS_BO_BE) + return be64_to_cpu((__force __be64)a); + else + return le64_to_cpu((__force __le64)a); +} /* * File modes. File types above 0xf000 are vxfs internal only, they should @@ -247,13 +273,6 @@ enum { #define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) #define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) - -/* - * Get filesystem private data from VFS inode. - */ -#define VXFS_INO(ip) \ - ((struct vxfs_inode_info *)(ip)->i_private) - /* * Get filesystem private data from VFS superblock. */ 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) { struct super_block *sb = ip->i_sb; struct vxfs_inode_info *vip = VXFS_INO(ip); + struct vxfs_sb_info *sbi = VXFS_SBI(sb); unsigned long bsize = sb->s_blocksize; - u32 indsize = vip->vii_ext4.ve4_indsize; + u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize); int i; if (indsize > sb->s_blocksize) @@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn) for (i = 0; i < VXFS_NDADDR; i++) { struct direct *d = vip->vii_ext4.ve4_direct + i; - if (bn >= 0 && bn < d->size) - return (bn + d->extent); - bn -= d->size; + if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size)) + return (bn + fs32_to_cpu(sbi, d->extent)); + bn -= fs32_to_cpu(sbi, d->size); } if ((bn / (indsize * indsize * bsize / 4)) == 0) { struct buffer_head *buf; daddr_t bno; - u32 *indir; + __fs32 *indir; - buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]); + buf = sb_bread(sb, + fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0])); if (!buf || !buffer_mapped(buf)) goto fail_buf; - indir = (u32 *)buf->b_data; - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize); + indir = (__fs32 *)buf->b_data; + bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) + + (bn % indsize); brelse(buf); return bno; @@ -127,6 +130,7 @@ fail_buf: static daddr_t vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) { + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); struct buffer_head *bp = NULL; daddr_t pblock = 0; int i; @@ -142,24 +146,27 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) typ = ((struct vxfs_typed *)bp->b_data) + (i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); - off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK; if (block < off) { brelse(bp); continue; } - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { + switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >> + VXFS_TYPED_TYPESHIFT)) { case VXFS_TYPED_INDIRECT: - pblock = vxfs_bmap_indir(ip, typ->vt_block, - typ->vt_size, block - off); + pblock = vxfs_bmap_indir(ip, + fs32_to_cpu(sbi, typ->vt_block), + fs32_to_cpu(sbi, typ->vt_size), + block - off); if (pblock == -2) break; goto out; case VXFS_TYPED_DATA: - if ((block - off) >= typ->vt_size) + if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size)) break; - pblock = (typ->vt_block + block - off); + pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off; goto out; case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_DATA_DEV4: { @@ -167,13 +174,15 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) (struct vxfs_typed_dev4 *)typ; printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", - (unsigned long long) typ4->vd4_block, - (unsigned long long) typ4->vd4_size, - typ4->vd4_dev); + printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n", + fs64_to_cpu(sbi, typ4->vd4_block), + fs64_to_cpu(sbi, typ4->vd4_size), + fs32_to_cpu(sbi, typ4->vd4_dev)); goto fail; } default: + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__, + __LINE__, fs64_to_cpu(sbi, typ->vt_hdr)); BUG(); } brelse(bp); @@ -201,28 +210,33 @@ static daddr_t vxfs_bmap_typed(struct inode *ip, long iblock) { struct vxfs_inode_info *vip = VXFS_INO(ip); + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); daddr_t pblock = 0; int i; for (i = 0; i < VXFS_NTYPED; i++) { struct vxfs_typed *typ = vip->vii_org.typed + i; - int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + u64 hdr = fs64_to_cpu(sbi, typ->vt_hdr); + int64_t off = (hdr & VXFS_TYPED_OFFSETMASK); #ifdef DIAGNOSTIC vxfs_typdump(typ); #endif if (iblock < off) continue; - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { + switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) { case VXFS_TYPED_INDIRECT: - pblock = vxfs_bmap_indir(ip, typ->vt_block, - typ->vt_size, iblock - off); + pblock = vxfs_bmap_indir(ip, + fs32_to_cpu(sbi, typ->vt_block), + fs32_to_cpu(sbi, typ->vt_size), + iblock - off); if (pblock == -2) break; return (pblock); case VXFS_TYPED_DATA: - if ((iblock - off) < typ->vt_size) - return (typ->vt_block + iblock - off); + if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size)) + return (fs32_to_cpu(sbi, typ->vt_block) + + iblock - off); break; case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_DATA_DEV4: { @@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock) (struct vxfs_typed_dev4 *)typ; printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", - (unsigned long long) typ4->vd4_block, - (unsigned long long) typ4->vd4_size, - typ4->vd4_dev); + printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n", + fs64_to_cpu(sbi, typ4->vd4_block), + fs64_to_cpu(sbi, typ4->vd4_size), + fs32_to_cpu(sbi, typ4->vd4_dev)); return 0; } 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 @@ * Linux driver for now. */ struct vxfs_dirblk { - u_int16_t d_free; /* free space in dirblock */ - u_int16_t d_nhash; /* no of hash chains */ - u_int16_t d_hash[1]; /* hash chain */ + __fs16 d_free; /* free space in dirblock */ + __fs16 d_nhash; /* no of hash chains */ + __fs16 d_hash[1]; /* hash chain */ }; /* @@ -63,10 +63,10 @@ struct vxfs_dirblk { * VxFS directory entry. */ struct vxfs_direct { - vx_ino_t d_ino; /* inode number */ - u_int16_t d_reclen; /* record length */ - u_int16_t d_namelen; /* d_name length */ - u_int16_t d_hashnext; /* next hash entry */ + __fs32 d_ino; /* inode number */ + __fs16 d_reclen; /* record length */ + __fs16 d_namelen; /* d_name length */ + __fs16 d_hashnext; /* next hash entry */ char d_name[VXFS_NAMELEN]; /* name */ }; @@ -87,6 +87,7 @@ struct vxfs_direct { /* * VXFS_DIRBLKOV is the overhead of a specific dirblock. */ -#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4) +#define VXFS_DIRBLKOV(sbi, dbp) \ + ((sizeof(short) * fs16_to_cpu(sbi, dbp->d_nhash)) + 4) #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 *); /* vxfs_inode.c */ extern const struct address_space_operations vxfs_immed_aops; -extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); -extern struct inode * vxfs_get_fake_inode(struct super_block *, - struct vxfs_inode_info *); -extern void vxfs_put_fake_inode(struct inode *); -extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); -extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); -extern struct inode * vxfs_iget(struct super_block *, ino_t); +extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); +extern struct inode *vxfs_stiget(struct super_block *, ino_t); +extern struct inode *vxfs_iget(struct super_block *, ino_t); extern void vxfs_evict_inode(struct inode *); /* 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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,31 +109,26 @@ vxfs_read_fshead(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); struct vxfs_fsh *pfp, *sfp; - struct vxfs_inode_info *vip, *tip; + struct vxfs_inode_info *vip; - vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); - if (!vip) { + infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); + if (!infp->vsi_fship) { printk(KERN_ERR "vxfs: unable to read fsh inode\n"); return -EINVAL; } + + vip = VXFS_INO(infp->vsi_fship); if (!VXFS_ISFSH(vip)) { printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", vip->vii_mode & VXFS_TYPE_MASK); - goto out_free_fship; + goto out_iput_fship; } - #ifdef DIAGNOSTIC printk("vxfs: fsh inode dump:\n"); vxfs_dumpi(vip, infp->vsi_fshino); #endif - infp->vsi_fship = vxfs_get_fake_inode(sbp, vip); - if (!infp->vsi_fship) { - printk(KERN_ERR "vxfs: unable to get fsh inode\n"); - goto out_free_fship; - } - sfp = vxfs_getfsh(infp->vsi_fship, 0); if (!sfp) { printk(KERN_ERR "vxfs: unable to get structural fsh\n"); @@ -153,14 +149,10 @@ vxfs_read_fshead(struct super_block *sbp) vxfs_dumpfsh(pfp); #endif - tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); - if (!tip) - goto out_free_pfp; - - infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip); + infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext, + fs32_to_cpu(infp, sfp->fsh_ilistino[0])); if (!infp->vsi_stilist) { printk(KERN_ERR "vxfs: unable to get structural list inode\n"); - kfree(tip); goto out_free_pfp; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { @@ -169,13 +161,9 @@ vxfs_read_fshead(struct super_block *sbp) goto out_iput_stilist; } - tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); - if (!tip) - goto out_iput_stilist; - infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); + infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0])); if (!infp->vsi_ilist) { printk(KERN_ERR "vxfs: unable to get inode list inode\n"); - kfree(tip); goto out_iput_stilist; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { @@ -184,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp) goto out_iput_ilist; } + kfree(pfp); + kfree(sfp); return 0; out_iput_ilist: @@ -197,7 +187,4 @@ vxfs_read_fshead(struct super_block *sbp) out_iput_fship: iput(infp->vsi_fship); return -EINVAL; - out_free_fship: - kfree(vip); - return -EINVAL; } 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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,20 +43,20 @@ * Fileset header */ struct vxfs_fsh { - u_int32_t fsh_version; /* fileset header version */ - u_int32_t fsh_fsindex; /* fileset index */ - u_int32_t fsh_time; /* modification time - sec */ - u_int32_t fsh_utime; /* modification time - usec */ - u_int32_t fsh_extop; /* extop flags */ - vx_ino_t fsh_ninodes; /* allocated inodes */ - u_int32_t fsh_nau; /* number of IAUs */ - u_int32_t fsh_old_ilesize; /* old size of ilist */ - u_int32_t fsh_dflags; /* flags */ - u_int32_t fsh_quota; /* quota limit */ - vx_ino_t fsh_maxinode; /* maximum inode number */ - vx_ino_t fsh_iauino; /* IAU inode */ - vx_ino_t fsh_ilistino[2]; /* ilist inodes */ - vx_ino_t fsh_lctino; /* link count table inode */ + __fs32 fsh_version; /* fileset header version */ + __fs32 fsh_fsindex; /* fileset index */ + __fs32 fsh_time; /* modification time - sec */ + __fs32 fsh_utime; /* modification time - usec */ + __fs32 fsh_extop; /* extop flags */ + __fs32 fsh_ninodes; /* allocated inodes */ + __fs32 fsh_nau; /* number of IAUs */ + __fs32 fsh_old_ilesize; /* old size of ilist */ + __fs32 fsh_dflags; /* flags */ + __fs32 fsh_quota; /* quota limit */ + __fs32 fsh_maxinode; /* maximum inode number */ + __fs32 fsh_iauino; /* IAU inode */ + __fs32 fsh_ilistino[2]; /* ilist inodes */ + __fs32 fsh_lctino; /* link count table inode */ /* * 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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,9 +43,6 @@ #include "vxfs_extern.h" -struct kmem_cache *vxfs_inode_cachep; - - #ifdef DIAGNOSTIC /* * Dump inode contents (partially). @@ -68,6 +66,83 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) } #endif +/** + * vxfs_transmod - mode for a VxFS inode + * @vip: VxFS inode + * + * Description: + * vxfs_transmod returns a Linux mode_t for a given + * VxFS inode structure. + */ +static __inline__ umode_t +vxfs_transmod(struct vxfs_inode_info *vip) +{ + umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; + + if (VXFS_ISFIFO(vip)) + ret |= S_IFIFO; + if (VXFS_ISCHR(vip)) + ret |= S_IFCHR; + if (VXFS_ISDIR(vip)) + ret |= S_IFDIR; + if (VXFS_ISBLK(vip)) + ret |= S_IFBLK; + if (VXFS_ISLNK(vip)) + ret |= S_IFLNK; + if (VXFS_ISREG(vip)) + ret |= S_IFREG; + if (VXFS_ISSOC(vip)) + ret |= S_IFSOCK; + + return (ret); +} + +static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, + struct vxfs_inode_info *vip, struct vxfs_dinode *dip) +{ + struct inode *inode = &vip->vfs_inode; + + vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); + vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); + vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); + vip->vii_gid = fs32_to_cpu(sbi, dip->vdi_gid); + vip->vii_size = fs64_to_cpu(sbi, dip->vdi_size); + vip->vii_atime = fs32_to_cpu(sbi, dip->vdi_atime); + vip->vii_autime = fs32_to_cpu(sbi, dip->vdi_autime); + vip->vii_mtime = fs32_to_cpu(sbi, dip->vdi_mtime); + vip->vii_mutime = fs32_to_cpu(sbi, dip->vdi_mutime); + vip->vii_ctime = fs32_to_cpu(sbi, dip->vdi_ctime); + vip->vii_cutime = fs32_to_cpu(sbi, dip->vdi_cutime); + vip->vii_orgtype = dip->vdi_orgtype; + + vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks); + vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen); + + if (VXFS_ISDIR(vip)) + vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot); + else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip)) + vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev); + + /* don't endian swap the fields that differ by orgtype */ + memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); + + inode->i_mode = vxfs_transmod(vip); + i_uid_write(inode, (uid_t)vip->vii_uid); + i_gid_write(inode, (gid_t)vip->vii_gid); + + set_nlink(inode, vip->vii_nlink); + inode->i_size = vip->vii_size; + + inode->i_atime.tv_sec = vip->vii_atime; + inode->i_ctime.tv_sec = vip->vii_ctime; + inode->i_mtime.tv_sec = vip->vii_mtime; + inode->i_atime.tv_nsec = 0; + inode->i_ctime.tv_nsec = 0; + inode->i_mtime.tv_nsec = 0; + + inode->i_blocks = vip->vii_blocks; + inode->i_generation = vip->vii_gen; +} /** * vxfs_blkiget - find inode based on extent # @@ -85,50 +160,55 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) * buffercache. This function should not be used outside the * read_super() method, otherwise the data may be incoherent. */ -struct vxfs_inode_info * +struct inode * vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) { struct buffer_head *bp; + struct inode *inode; u_long block, offset; + inode = new_inode(sbp); + if (!inode) + return NULL; + inode->i_ino = get_next_ino(); + block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); bp = sb_bread(sbp, block); if (bp && buffer_mapped(bp)) { - struct vxfs_inode_info *vip; + struct vxfs_inode_info *vip = VXFS_INO(inode); struct vxfs_dinode *dip; - if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) - goto fail; dip = (struct vxfs_dinode *)(bp->b_data + offset); - memcpy(vip, dip, sizeof(*vip)); + dip2vip_cpy(VXFS_SBI(sbp), vip, dip); + vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif brelse(bp); - return (vip); + return inode; } -fail: printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); brelse(bp); + iput(inode); return NULL; } /** * __vxfs_iget - generic find inode facility - * @sbp: VFS superblock - * @ino: inode number * @ilistp: inode list + * @vip: VxFS inode to fill in + * @ino: inode number * * Description: * Search the for inode number @ino in the filesystem * described by @sbp. Use the specified inode table (@ilistp). - * Returns the matching VxFS inode on success, else an error code. + * Returns the matching inode on success, else an error code. */ -static struct vxfs_inode_info * -__vxfs_iget(ino_t ino, struct inode *ilistp) +static int +__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino) { struct page *pp; u_long offset; @@ -137,28 +217,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp) pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); if (!IS_ERR(pp)) { - struct vxfs_inode_info *vip; struct vxfs_dinode *dip; caddr_t kaddr = (char *)page_address(pp); - if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) - goto fail; dip = (struct vxfs_dinode *)(kaddr + offset); - memcpy(vip, dip, sizeof(*vip)); + dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip); + vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif vxfs_put_page(pp); - return (vip); + return 0; } - printk(KERN_WARNING "vxfs: error on page %p\n", pp); - return ERR_CAST(pp); - -fail: - printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); - vxfs_put_page(pp); - return ERR_PTR(-ENOMEM); + printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n", + pp, (unsigned long)ino); + return PTR_ERR(pp); } /** @@ -169,116 +243,26 @@ fail: * Description: * Find inode @ino in the filesystem described by @sbp using * the structural inode list. - * Returns the matching VxFS inode on success, else a NULL pointer. - */ -struct vxfs_inode_info * -vxfs_stiget(struct super_block *sbp, ino_t ino) -{ - struct vxfs_inode_info *vip; - - vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); - return IS_ERR(vip) ? NULL : vip; -} - -/** - * vxfs_transmod - mode for a VxFS inode - * @vip: VxFS inode - * - * Description: - * vxfs_transmod returns a Linux mode_t for a given - * VxFS inode structure. - */ -static __inline__ umode_t -vxfs_transmod(struct vxfs_inode_info *vip) -{ - umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; - - if (VXFS_ISFIFO(vip)) - ret |= S_IFIFO; - if (VXFS_ISCHR(vip)) - ret |= S_IFCHR; - if (VXFS_ISDIR(vip)) - ret |= S_IFDIR; - if (VXFS_ISBLK(vip)) - ret |= S_IFBLK; - if (VXFS_ISLNK(vip)) - ret |= S_IFLNK; - if (VXFS_ISREG(vip)) - ret |= S_IFREG; - if (VXFS_ISSOC(vip)) - ret |= S_IFSOCK; - - return (ret); -} - -/** - * vxfs_iinit- helper to fill inode fields - * @ip: VFS inode - * @vip: VxFS inode - * - * Description: - * vxfs_instino is a helper function to fill in all relevant - * fields in @ip from @vip. - */ -static void -vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) -{ - - ip->i_mode = vxfs_transmod(vip); - i_uid_write(ip, (uid_t)vip->vii_uid); - i_gid_write(ip, (gid_t)vip->vii_gid); - - set_nlink(ip, vip->vii_nlink); - ip->i_size = vip->vii_size; - - ip->i_atime.tv_sec = vip->vii_atime; - ip->i_ctime.tv_sec = vip->vii_ctime; - ip->i_mtime.tv_sec = vip->vii_mtime; - ip->i_atime.tv_nsec = 0; - ip->i_ctime.tv_nsec = 0; - ip->i_mtime.tv_nsec = 0; - - ip->i_blocks = vip->vii_blocks; - ip->i_generation = vip->vii_gen; - - ip->i_private = vip; - -} - -/** - * vxfs_get_fake_inode - get fake inode structure - * @sbp: filesystem superblock - * @vip: fspriv inode - * - * Description: - * vxfs_fake_inode gets a fake inode (not in the inode hash) for a - * superblock, vxfs_inode pair. - * Returns the filled VFS inode. + * Returns the matching inode on success, else a NULL pointer. */ struct inode * -vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) +vxfs_stiget(struct super_block *sbp, ino_t ino) { - struct inode *ip = NULL; - - if ((ip = new_inode(sbp))) { - ip->i_ino = get_next_ino(); - vxfs_iinit(ip, vip); - ip->i_mapping->a_ops = &vxfs_aops; + struct inode *inode; + int error; + + inode = new_inode(sbp); + if (!inode) + return NULL; + inode->i_ino = get_next_ino(); + + error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino); + if (error) { + iput(inode); + return NULL; } - return (ip); -} -/** - * vxfs_put_fake_inode - free faked inode - * *ip: VFS inode - * - * Description: - * vxfs_put_fake_inode frees all data associated with @ip. - */ -void -vxfs_put_fake_inode(struct inode *ip) -{ - iput(ip); + return inode; } /** @@ -296,6 +280,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino) struct vxfs_inode_info *vip; const struct address_space_operations *aops; struct inode *ip; + int error; ip = iget_locked(sbp, ino); if (!ip) @@ -303,14 +288,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino) if (!(ip->i_state & I_NEW)) return ip; - vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist); - if (IS_ERR(vip)) { + vip = VXFS_INO(ip); + error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino); + if (error) { iget_failed(ip); - return ERR_CAST(vip); + return ERR_PTR(error); } - vxfs_iinit(ip, vip); - if (VXFS_ISIMMED(vip)) aops = &vxfs_immed_aops; else @@ -341,12 +325,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino) return ip; } -static void vxfs_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(vxfs_inode_cachep, inode->i_private); -} - /** * vxfs_evict_inode - remove inode from main memory * @ip: inode to discard. @@ -360,5 +338,4 @@ vxfs_evict_inode(struct inode *ip) { truncate_inode_pages_final(&ip->i_data); clear_inode(ip); - call_rcu(&ip->i_rcu, vxfs_i_callback); } 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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,74 +67,74 @@ enum { * Data stored immediately in the inode. */ struct vxfs_immed { - u_int8_t vi_immed[VXFS_NIMMED]; + __u8 vi_immed[VXFS_NIMMED]; }; struct vxfs_ext4 { - u_int32_t ve4_spare; /* ?? */ - u_int32_t ve4_indsize; /* Indirect extent size */ - vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ + __fs32 ve4_spare; /* ?? */ + __fs32 ve4_indsize; /* Indirect extent size */ + __fs32 ve4_indir[VXFS_NIADDR]; /* Indirect extents */ struct direct { /* Direct extents */ - vx_daddr_t extent; /* Extent number */ - int32_t size; /* Size of extent */ + __fs32 extent; /* Extent number */ + __fs32 size; /* Size of extent */ } ve4_direct[VXFS_NDADDR]; }; struct vxfs_typed { - u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ - vx_daddr_t vt_block; /* Extent block */ - int32_t vt_size; /* Size in blocks */ + __fs64 vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ + __fs32 vt_block; /* Extent block */ + __fs32 vt_size; /* Size in blocks */ }; struct vxfs_typed_dev4 { - u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ - u_int64_t vd4_block; /* Extent block */ - u_int64_t vd4_size; /* Size in blocks */ - int32_t vd4_dev; /* Device ID */ - u_int32_t __pad1; + __fs64 vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ + __fs64 vd4_block; /* Extent block */ + __fs64 vd4_size; /* Size in blocks */ + __fs32 vd4_dev; /* Device ID */ + __u8 __pad1; }; /* * The inode as contained on the physical device. */ struct vxfs_dinode { - int32_t vdi_mode; - u_int32_t vdi_nlink; /* Link count */ - u_int32_t vdi_uid; /* UID */ - u_int32_t vdi_gid; /* GID */ - u_int64_t vdi_size; /* Inode size in bytes */ - u_int32_t vdi_atime; /* Last time accessed - sec */ - u_int32_t vdi_autime; /* Last time accessed - usec */ - u_int32_t vdi_mtime; /* Last modify time - sec */ - u_int32_t vdi_mutime; /* Last modify time - usec */ - u_int32_t vdi_ctime; /* Create time - sec */ - u_int32_t vdi_cutime; /* Create time - usec */ - u_int8_t vdi_aflags; /* Allocation flags */ - u_int8_t vdi_orgtype; /* Organisation type */ - u_int16_t vdi_eopflags; - u_int32_t vdi_eopdata; + __fs32 vdi_mode; + __fs32 vdi_nlink; /* Link count */ + __fs32 vdi_uid; /* UID */ + __fs32 vdi_gid; /* GID */ + __fs64 vdi_size; /* Inode size in bytes */ + __fs32 vdi_atime; /* Last time accessed - sec */ + __fs32 vdi_autime; /* Last time accessed - usec */ + __fs32 vdi_mtime; /* Last modify time - sec */ + __fs32 vdi_mutime; /* Last modify time - usec */ + __fs32 vdi_ctime; /* Create time - sec */ + __fs32 vdi_cutime; /* Create time - usec */ + __u8 vdi_aflags; /* Allocation flags */ + __u8 vdi_orgtype; /* Organisation type */ + __fs16 vdi_eopflags; + __fs32 vdi_eopdata; union { - u_int32_t rdev; - u_int32_t dotdot; + __fs32 rdev; + __fs32 dotdot; struct { - u_int32_t reserved; - u_int32_t fixextsize; + __u32 reserved; + __fs32 fixextsize; } i_regular; struct { - u_int32_t matchino; - u_int32_t fsetindex; + __fs32 matchino; + __fs32 fsetindex; } i_vxspec; - u_int64_t align; + __u64 align; } vdi_ftarea; - u_int32_t vdi_blocks; /* How much blocks does inode occupy */ - u_int32_t vdi_gen; /* Inode generation */ - u_int64_t vdi_version; /* Version */ + __fs32 vdi_blocks; /* How much blocks does inode occupy */ + __fs32 vdi_gen; /* Inode generation */ + __fs64 vdi_version; /* Version */ union { struct vxfs_immed immed; struct vxfs_ext4 ext4; struct vxfs_typed typed[VXFS_NTYPED]; } vdi_org; - u_int32_t vdi_iattrino; + __fs32 vdi_iattrino; }; #define vdi_rdev vdi_ftarea.rdev @@ -149,32 +150,45 @@ struct vxfs_dinode { /* * The inode as represented in the main memory. - * - * TBD: This should become a separate structure... */ -#define vxfs_inode_info vxfs_dinode - -#define vii_mode vdi_mode -#define vii_uid vdi_uid -#define vii_gid vdi_gid -#define vii_nlink vdi_nlink -#define vii_size vdi_size -#define vii_atime vdi_atime -#define vii_ctime vdi_ctime -#define vii_mtime vdi_mtime -#define vii_blocks vdi_blocks -#define vii_org vdi_org -#define vii_orgtype vdi_orgtype -#define vii_gen vdi_gen - -#define vii_rdev vdi_ftarea.rdev -#define vii_dotdot vdi_ftarea.dotdot -#define vii_fixextsize vdi_ftarea.regular.fixextsize -#define vii_matchino vdi_ftarea.vxspec.matchino -#define vii_fsetindex vdi_ftarea.vxspec.fsetindex - -#define vii_immed vdi_org.immed -#define vii_ext4 vdi_org.ext4 -#define vii_typed vdi_org.typed +struct vxfs_inode_info { + struct inode vfs_inode; + + __u32 vii_mode; + __u32 vii_nlink; /* Link count */ + __u32 vii_uid; /* UID */ + __u32 vii_gid; /* GID */ + __u64 vii_size; /* Inode size in bytes */ + __u32 vii_atime; /* Last time accessed - sec */ + __u32 vii_autime; /* Last time accessed - usec */ + __u32 vii_mtime; /* Last modify time - sec */ + __u32 vii_mutime; /* Last modify time - usec */ + __u32 vii_ctime; /* Create time - sec */ + __u32 vii_cutime; /* Create time - usec */ + __u8 vii_orgtype; /* Organisation type */ + union { + __u32 rdev; + __u32 dotdot; + } vii_ftarea; + __u32 vii_blocks; /* How much blocks does inode occupy */ + __u32 vii_gen; /* Inode generation */ + union { + struct vxfs_immed immed; + struct vxfs_ext4 ext4; + struct vxfs_typed typed[VXFS_NTYPED]; + } vii_org; +}; + +#define vii_rdev vii_ftarea.rdev +#define vii_dotdot vii_ftarea.dotdot + +#define vii_immed vii_org.immed +#define vii_ext4 vii_org.ext4 +#define vii_typed vii_org.typed + +static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode) +{ + return container_of(inode, struct vxfs_inode_info, vfs_inode); +} #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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,33 +62,6 @@ const struct file_operations vxfs_dir_operations = { .iterate_shared = vxfs_readdir, }; -static inline u_long -dir_blocks(struct inode *ip) -{ - u_long bsize = ip->i_sb->s_blocksize; - return (ip->i_size + bsize - 1) & ~(bsize - 1); -} - -/* - * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure. - * - * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller. - */ -static inline int -vxfs_match(int len, const char * const name, struct vxfs_direct *de) -{ - if (len != de->d_namelen) - return 0; - if (!de->d_ino) - return 0; - return !memcmp(name, de->d_name, len); -} - -static inline struct vxfs_direct * -vxfs_next_entry(struct vxfs_direct *de) -{ - return ((struct vxfs_direct *)((char*)de + de->d_reclen)); -} /** * vxfs_find_entry - find a mathing directory entry for a dentry @@ -106,50 +80,64 @@ vxfs_next_entry(struct vxfs_direct *de) static struct vxfs_direct * vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) { - u_long npages, page, nblocks, pblocks, block; - u_long bsize = ip->i_sb->s_blocksize; - const char *name = dp->d_name.name; - int namelen = dp->d_name.len; - - npages = dir_pages(ip); - nblocks = dir_blocks(ip); - pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb); - - for (page = 0; page < npages; page++) { - caddr_t kaddr; - struct page *pp; + u_long bsize = ip->i_sb->s_blocksize; + const char *name = dp->d_name.name; + int namelen = dp->d_name.len; + loff_t limit = VXFS_DIRROUND(ip->i_size); + struct vxfs_direct *de_exit = NULL; + loff_t pos = 0; + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); - pp = vxfs_get_page(ip->i_mapping, page); + while (pos < limit) { + struct page *pp; + char *kaddr; + int pg_ofs = pos & ~PAGE_MASK; + + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT); if (IS_ERR(pp)) - continue; - kaddr = (caddr_t)page_address(pp); - - for (block = 0; block <= nblocks && block <= pblocks; block++) { - caddr_t baddr, limit; - struct vxfs_dirblk *dbp; - struct vxfs_direct *de; - - baddr = kaddr + (block * bsize); - limit = baddr + bsize - VXFS_DIRLEN(1); - - dbp = (struct vxfs_dirblk *)baddr; - de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp)); - - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { - if (!de->d_reclen) - break; - if (!de->d_ino) - continue; - if (vxfs_match(namelen, name, de)) { - *ppp = pp; - return (de); - } + return NULL; + kaddr = (char *)page_address(pp); + + while (pg_ofs < PAGE_SIZE && pos < limit) { + struct vxfs_direct *de; + + if ((pos & (bsize - 1)) < 4) { + struct vxfs_dirblk *dbp = + (struct vxfs_dirblk *) + (kaddr + (pos & ~PAGE_MASK)); + int overhead = VXFS_DIRBLKOV(sbi, dbp); + + pos += overhead; + pg_ofs += overhead; + } + de = (struct vxfs_direct *)(kaddr + pg_ofs); + + if (!de->d_reclen) { + pos += bsize - 1; + pos &= ~(bsize - 1); + break; + } + + pg_ofs += fs16_to_cpu(sbi, de->d_reclen); + pos += fs16_to_cpu(sbi, de->d_reclen); + if (!de->d_ino) + continue; + + if (namelen != fs16_to_cpu(sbi, de->d_namelen)) + continue; + if (!memcmp(name, de->d_name, namelen)) { + *ppp = pp; + de_exit = de; + break; } } - vxfs_put_page(pp); + if (!de_exit) + vxfs_put_page(pp); + else + break; } - return NULL; + return de_exit; } /** @@ -173,7 +161,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp) de = vxfs_find_entry(dip, dp, &pp); if (de) { - ino = de->d_ino; + ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino); kunmap(pp); put_page(pp); } @@ -233,74 +221,80 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx) struct inode *ip = file_inode(fp); struct super_block *sbp = ip->i_sb; u_long bsize = sbp->s_blocksize; - u_long page, npages, block, pblocks, nblocks, offset; - loff_t pos; + loff_t pos, limit; + struct vxfs_sb_info *sbi = VXFS_SBI(sbp); if (ctx->pos == 0) { if (!dir_emit_dot(fp, ctx)) - return 0; - ctx->pos = 1; + goto out; + ctx->pos++; } if (ctx->pos == 1) { if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR)) - return 0; - ctx->pos = 2; + goto out; + ctx->pos++; } - pos = ctx->pos - 2; - - if (pos > VXFS_DIRROUND(ip->i_size)) - return 0; - npages = dir_pages(ip); - nblocks = dir_blocks(ip); - pblocks = VXFS_BLOCK_PER_PAGE(sbp); + limit = VXFS_DIRROUND(ip->i_size); + if (ctx->pos > limit) + goto out; - page = pos >> PAGE_SHIFT; - offset = pos & ~PAGE_MASK; - block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; + pos = ctx->pos & ~3L; - for (; page < npages; page++, block = 0) { - char *kaddr; - struct page *pp; + while (pos < limit) { + struct page *pp; + char *kaddr; + int pg_ofs = pos & ~PAGE_MASK; + int rc = 0; - pp = vxfs_get_page(ip->i_mapping, page); + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT); if (IS_ERR(pp)) - continue; + return -ENOMEM; + kaddr = (char *)page_address(pp); - for (; block <= nblocks && block <= pblocks; block++) { - char *baddr, *limit; - struct vxfs_dirblk *dbp; - struct vxfs_direct *de; + while (pg_ofs < PAGE_SIZE && pos < limit) { + struct vxfs_direct *de; - baddr = kaddr + (block * bsize); - limit = baddr + bsize - VXFS_DIRLEN(1); - - dbp = (struct vxfs_dirblk *)baddr; - de = (struct vxfs_direct *) - (offset ? - (kaddr + offset) : - (baddr + VXFS_DIRBLKOV(dbp))); - - for (; (char *)de <= limit; de = vxfs_next_entry(de)) { - if (!de->d_reclen) - break; - if (!de->d_ino) - continue; - - offset = (char *)de - kaddr; - ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; - if (!dir_emit(ctx, de->d_name, de->d_namelen, - de->d_ino, DT_UNKNOWN)) { - vxfs_put_page(pp); - return 0; - } + if ((pos & (bsize - 1)) < 4) { + struct vxfs_dirblk *dbp = + (struct vxfs_dirblk *) + (kaddr + (pos & ~PAGE_MASK)); + int overhead = VXFS_DIRBLKOV(sbi, dbp); + + pos += overhead; + pg_ofs += overhead; + } + de = (struct vxfs_direct *)(kaddr + pg_ofs); + + if (!de->d_reclen) { + pos += bsize - 1; + pos &= ~(bsize - 1); + break; + } + + pg_ofs += fs16_to_cpu(sbi, de->d_reclen); + pos += fs16_to_cpu(sbi, de->d_reclen); + if (!de->d_ino) + continue; + + rc = dir_emit(ctx, de->d_name, + fs16_to_cpu(sbi, de->d_namelen), + fs32_to_cpu(sbi, de->d_ino), + DT_UNKNOWN); + if (!rc) { + /* the dir entry was not read, fix pos. */ + pos -= fs16_to_cpu(sbi, de->d_reclen); + break; } - offset = 0; } vxfs_put_page(pp); - offset = 0; + if (!rc) + break; } - ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; + + ctx->pos = pos | 2; + +out: return 0; } 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 vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) { BUG_ON(infp->vsi_fshino); - infp->vsi_fshino = fshp->olt_fsino[0]; + infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]); } static inline void vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) { BUG_ON(infp->vsi_iext); - infp->vsi_iext = ilistp->olt_iext[0]; + infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]); } static inline u_long @@ -81,13 +81,12 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize) struct vxfs_olt *op; char *oaddr, *eaddr; - bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize)); if (!bp || !bp->b_data) goto fail; op = (struct vxfs_olt *)bp->b_data; - if (op->olt_magic != VXFS_OLT_MAGIC) { + if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) { printk(KERN_NOTICE "vxfs: ivalid olt magic number\n"); goto fail; } @@ -102,14 +101,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize) goto fail; } - oaddr = bp->b_data + op->olt_size; + oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size); eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize); while (oaddr < eaddr) { struct vxfs_oltcommon *ocp = (struct vxfs_oltcommon *)oaddr; - switch (ocp->olt_type) { + switch (fs32_to_cpu(infp, ocp->olt_type)) { case VXFS_OLT_FSHEAD: vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp); break; @@ -118,11 +117,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize) break; } - oaddr += ocp->olt_size; + oaddr += fs32_to_cpu(infp, ocp->olt_size); } brelse(bp); - return 0; + return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL; fail: 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 { * the initial inode list, the fileset header or the device configuration. */ struct vxfs_olt { - u_int32_t olt_magic; /* magic number */ - u_int32_t olt_size; /* size of this entry */ - u_int32_t olt_checksum; /* checksum of extent */ - u_int32_t __unused1; /* ??? */ - u_int32_t olt_mtime; /* time of last mod. (sec) */ - u_int32_t olt_mutime; /* time of last mod. (usec) */ - u_int32_t olt_totfree; /* free space in OLT extent */ - vx_daddr_t olt_extents[2]; /* addr of this extent, replica */ - u_int32_t olt_esize; /* size of this extent */ - vx_daddr_t olt_next[2]; /* addr of next extent, replica */ - u_int32_t olt_nsize; /* size of next extent */ - u_int32_t __unused2; /* align to 8 byte boundary */ + __fs32 olt_magic; /* magic number */ + __fs32 olt_size; /* size of this entry */ + __fs32 olt_checksum; /* checksum of extent */ + __u32 __unused1; /* ??? */ + __fs32 olt_mtime; /* time of last mod. (sec) */ + __fs32 olt_mutime; /* time of last mod. (usec) */ + __fs32 olt_totfree; /* free space in OLT extent */ + __fs32 olt_extents[2]; /* addr of this extent, replica */ + __fs32 olt_esize; /* size of this extent */ + __fs32 olt_next[2]; /* addr of next extent, replica */ + __fs32 olt_nsize; /* size of next extent */ + __u32 __unused2; /* align to 8 byte boundary */ }; /* * VxFS common OLT entry (on disk). */ struct vxfs_oltcommon { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ }; /* * VxFS free OLT entry (on disk). */ struct vxfs_oltfree { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_fsize; /* size of this free record */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_fsize; /* size of this free record */ }; /* * VxFS initial-inode list (on disk). */ struct vxfs_oltilist { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_iext[2]; /* initial inode list, replica */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_iext[2]; /* initial inode list, replica */ }; /* * Current Usage Table */ struct vxfs_oltcut { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_cutino; /* inode of current usage table */ - u_int32_t __pad; /* unused, 8 byte align */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_cutino; /* inode of current usage table */ + __u8 __pad; /* unused, 8 byte align */ }; /* * Inodes containing Superblock, Intent log and OLTs */ struct vxfs_oltsb { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_sbino; /* inode of superblock file */ - u_int32_t __unused1; /* ??? */ - vx_ino_t olt_logino[2]; /* inode of log file,replica */ - vx_ino_t olt_oltino[2]; /* inode of OLT, replica */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_sbino; /* inode of superblock file */ + __u32 __unused1; /* ??? */ + __fs32 olt_logino[2]; /* inode of log file,replica */ + __fs32 olt_oltino[2]; /* inode of OLT, replica */ }; /* * Inode containing device configuration + it's replica */ struct vxfs_oltdev { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_devino[2]; /* inode of device config files */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_devino[2]; /* inode of device config files */ }; /* * Fileset header */ struct vxfs_oltfshead { - u_int32_t olt_type; /* type number */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_fsino[2]; /* inodes of fileset header */ + __fs32 olt_type; /* type number */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_fsino[2]; /* inodes of fileset header */ }; #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 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,22 +49,11 @@ #include "vxfs_inode.h" -MODULE_AUTHOR("Christoph Hellwig"); +MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski"); MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); MODULE_LICENSE("Dual BSD/GPL"); - - -static void vxfs_put_super(struct super_block *); -static int vxfs_statfs(struct dentry *, struct kstatfs *); -static int vxfs_remount(struct super_block *, int *, char *); - -static const struct super_operations vxfs_super_ops = { - .evict_inode = vxfs_evict_inode, - .put_super = vxfs_put_super, - .statfs = vxfs_statfs, - .remount_fs = vxfs_remount, -}; +static struct kmem_cache *vxfs_inode_cachep; /** * vxfs_put_super - free superblock resources @@ -79,9 +69,9 @@ vxfs_put_super(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); - vxfs_put_fake_inode(infp->vsi_fship); - vxfs_put_fake_inode(infp->vsi_ilist); - vxfs_put_fake_inode(infp->vsi_stilist); + iput(infp->vsi_fship); + iput(infp->vsi_ilist); + iput(infp->vsi_stilist); brelse(infp->vsi_bp); kfree(infp); @@ -109,14 +99,15 @@ static int vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) { struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); + struct vxfs_sb *raw_sb = infp->vsi_raw; bufp->f_type = VXFS_SUPER_MAGIC; bufp->f_bsize = dentry->d_sb->s_blocksize; - bufp->f_blocks = infp->vsi_raw->vs_dsize; - bufp->f_bfree = infp->vsi_raw->vs_free; + bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize); + bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free); bufp->f_bavail = 0; bufp->f_files = 0; - bufp->f_ffree = infp->vsi_raw->vs_ifree; + bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree); bufp->f_namelen = VXFS_NAMELEN; return 0; @@ -129,6 +120,81 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) return 0; } +static struct inode *vxfs_alloc_inode(struct super_block *sb) +{ + struct vxfs_inode_info *vi; + + vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL); + if (!vi) + return NULL; + inode_init_once(&vi->vfs_inode); + return &vi->vfs_inode; +} + +static void vxfs_i_callback(struct rcu_head *head) +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + + kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode)); +} + +static void vxfs_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, vxfs_i_callback); +} + +static const struct super_operations vxfs_super_ops = { + .alloc_inode = vxfs_alloc_inode, + .destroy_inode = vxfs_destroy_inode, + .evict_inode = vxfs_evict_inode, + .put_super = vxfs_put_super, + .statfs = vxfs_statfs, + .remount_fs = vxfs_remount, +}; + +static int vxfs_try_sb_magic(struct super_block *sbp, int silent, + unsigned blk, __fs32 magic) +{ + struct buffer_head *bp; + struct vxfs_sb *rsbp; + struct vxfs_sb_info *infp = VXFS_SBI(sbp); + int rc = -ENOMEM; + + bp = sb_bread(sbp, blk); + do { + if (!bp || !buffer_mapped(bp)) { + if (!silent) { + printk(KERN_WARNING + "vxfs: unable to read disk superblock at %u\n", + blk); + } + break; + } + + rc = -EINVAL; + rsbp = (struct vxfs_sb *)bp->b_data; + if (rsbp->vs_magic != magic) { + if (!silent) + printk(KERN_NOTICE + "vxfs: WRONG superblock magic %08x at %u\n", + rsbp->vs_magic, blk); + break; + } + + rc = 0; + infp->vsi_raw = rsbp; + infp->vsi_bp = bp; + } while (0); + + if (rc) { + infp->vsi_raw = NULL; + infp->vsi_bp = NULL; + brelse(bp); + } + + return rc; +} + /** * vxfs_read_super - read superblock into memory and initialize filesystem * @sbp: VFS superblock (to fill) @@ -149,10 +215,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) { struct vxfs_sb_info *infp; struct vxfs_sb *rsbp; - struct buffer_head *bp = NULL; u_long bsize; struct inode *root; int ret = -EINVAL; + u32 j; sbp->s_flags |= MS_RDONLY; @@ -168,42 +234,43 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out; } - bp = sb_bread(sbp, 1); - if (!bp || !buffer_mapped(bp)) { - if (!silent) { - printk(KERN_WARNING - "vxfs: unable to read disk superblock\n"); - } - goto out; - } + sbp->s_op = &vxfs_super_ops; + sbp->s_fs_info = infp; - rsbp = (struct vxfs_sb *)bp->b_data; - if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { + if (!vxfs_try_sb_magic(sbp, silent, 1, + (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) { + /* Unixware, x86 */ + infp->byte_order = VXFS_BO_LE; + } else if (!vxfs_try_sb_magic(sbp, silent, 8, + (__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) { + /* HP-UX, parisc */ + infp->byte_order = VXFS_BO_BE; + } else { if (!silent) - printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); + printk(KERN_NOTICE "vxfs: can't find superblock.\n"); goto out; } - if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { - printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", - rsbp->vs_version); + rsbp = infp->vsi_raw; + j = fs32_to_cpu(infp, rsbp->vs_version); + if ((j < 2 || j > 4) && !silent) { + printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j); goto out; } #ifdef DIAGNOSTIC - printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); - printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); + printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j); + printk(KERN_DEBUG "vxfs: blocksize: %d\n", + fs32_to_cpu(infp, rsbp->vs_bsize)); #endif - sbp->s_magic = rsbp->vs_magic; - sbp->s_fs_info = infp; + sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic); - infp->vsi_raw = rsbp; - infp->vsi_bp = bp; - infp->vsi_oltext = rsbp->vs_oltext[0]; - infp->vsi_oltsize = rsbp->vs_oltsize; + infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]); + infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize); - if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) { + j = fs32_to_cpu(infp, rsbp->vs_bsize); + if (!sb_set_blocksize(sbp, j)) { printk(KERN_WARNING "vxfs: unable to set final block size\n"); goto out; } @@ -218,7 +285,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out; } - sbp->s_op = &vxfs_super_ops; root = vxfs_iget(sbp, VXFS_ROOT_INO); if (IS_ERR(root)) { ret = PTR_ERR(root); @@ -233,11 +299,11 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) return 0; out_free_ilist: - vxfs_put_fake_inode(infp->vsi_fship); - vxfs_put_fake_inode(infp->vsi_ilist); - vxfs_put_fake_inode(infp->vsi_stilist); + iput(infp->vsi_fship); + iput(infp->vsi_ilist); + iput(infp->vsi_stilist); out: - brelse(bp); + brelse(infp->vsi_bp); kfree(infp); return ret; } |