freevxfs updates for 4.7:
- support for foreign endianess and HP-UP superblocks from Krzysztof Błaszkowski -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXmgdVAAoJEA+eU2VSBFGDougP/2qC4LcCGSmdhxPaoK9vBOh4 DZA5sHwwyxlDl+7rt8vDv8eVLMmkCURF3c9IJq2YIDxTW+3LYy/PWIp1mWbw2etj Ps+oS7zzqMWkEQpAQyN+1KNJelaZvJSuoI3e2+7hFDidyOf1myCV6UgOEPIeV0A9 Mi8qVxkO6PzVXKUEK8BTcB+e08+zjdSGuGJabBLpU9yBe2wHGkoVAqfedNS0d4Wc Rj+HPFBy/peWd72Au5rVI8EHs1GyUcyquHiSydGzlqHVM3xzLaDZuKXtRKZrpA2m tVdK+FElXykMWYhbCWSCQAImHDgZTUTgnZtKhW9OzDYHAokFQQrnv2YlAGrBGwow t/7ND7IBlq6INLfpidr/Jt/XA5FMNvLvsaCTKiiCyShIkIyKd6Xx/e7cxGsP7seQ JRPN3TY2geFdaFmctLDVlYqOgHcPKrfwNSXu0G1o9mtS2EVJnjLKobMRuMnFWFmo e8MEHbFgv5g2o31O5RVju3kB2AqP1V6KySSfY5jX5AvNCSuiAWtmxPDUiD4aU8qA 46Uk1wCET8M/eQjq6j5TMtkYIWn9jElQfkETIeXFF2xDniQMxt2kpn2KMef/8Qhs C3Z8wkb3bhJQd/8L6uZ0IHwxrKWL3FYu6xwYE2StbXASb/sNhAd/QNIodGqrP9z9 1I9/tod/Eq4at9ji+V52 =+CpR -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
0a7736d037
@ -5,12 +5,21 @@ config VXFS_FS
|
|||||||
FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
|
FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
|
||||||
file system format. VERITAS VxFS(TM) is the standard file system
|
file system format. VERITAS VxFS(TM) is the standard file system
|
||||||
of SCO UnixWare (and possibly others) and optionally available
|
of SCO UnixWare (and possibly others) and optionally available
|
||||||
for Sunsoft Solaris, HP-UX and many other operating systems.
|
for Sunsoft Solaris, HP-UX and many other operating systems. However
|
||||||
Currently only readonly access is supported.
|
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
|
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
|
fstab(5) is 'vxfs' as it describes the file system format, not
|
||||||
the actual driver.
|
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
|
To compile this as a module, choose M here: the module will be
|
||||||
called freevxfs. If unsure, say N.
|
called freevxfs. If unsure, say N.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -38,13 +39,6 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/types.h>
|
#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).
|
* Superblock magic number (vxfs_super->vs_magic).
|
||||||
*/
|
*/
|
||||||
@ -60,6 +54,14 @@ typedef int32_t vx_ino_t;
|
|||||||
*/
|
*/
|
||||||
#define VXFS_NEFREE 32
|
#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).
|
* VxFS superblock (disk).
|
||||||
@ -71,83 +73,83 @@ struct vxfs_sb {
|
|||||||
* Lots of this fields are no more used by version 2
|
* Lots of this fields are no more used by version 2
|
||||||
* and never filesystems.
|
* and never filesystems.
|
||||||
*/
|
*/
|
||||||
u_int32_t vs_magic; /* Magic number */
|
__fs32 vs_magic; /* Magic number */
|
||||||
int32_t vs_version; /* VxFS version */
|
__fs32 vs_version; /* VxFS version */
|
||||||
u_int32_t vs_ctime; /* create time - secs */
|
__fs32 vs_ctime; /* create time - secs */
|
||||||
u_int32_t vs_cutime; /* create time - usecs */
|
__fs32 vs_cutime; /* create time - usecs */
|
||||||
int32_t __unused1; /* unused */
|
__fs32 __unused1; /* unused */
|
||||||
int32_t __unused2; /* unused */
|
__fs32 __unused2; /* unused */
|
||||||
vx_daddr_t vs_old_logstart; /* obsolete */
|
__fs32 vs_old_logstart; /* obsolete */
|
||||||
vx_daddr_t vs_old_logend; /* obsolete */
|
__fs32 vs_old_logend; /* obsolete */
|
||||||
int32_t vs_bsize; /* block size */
|
__fs32 vs_bsize; /* block size */
|
||||||
int32_t vs_size; /* number of blocks */
|
__fs32 vs_size; /* number of blocks */
|
||||||
int32_t vs_dsize; /* number of data blocks */
|
__fs32 vs_dsize; /* number of data blocks */
|
||||||
u_int32_t vs_old_ninode; /* obsolete */
|
__fs32 vs_old_ninode; /* obsolete */
|
||||||
int32_t vs_old_nau; /* obsolete */
|
__fs32 vs_old_nau; /* obsolete */
|
||||||
int32_t __unused3; /* unused */
|
__fs32 __unused3; /* unused */
|
||||||
int32_t vs_old_defiextsize; /* obsolete */
|
__fs32 vs_old_defiextsize; /* obsolete */
|
||||||
int32_t vs_old_ilbsize; /* obsolete */
|
__fs32 vs_old_ilbsize; /* obsolete */
|
||||||
int32_t vs_immedlen; /* size of immediate data area */
|
__fs32 vs_immedlen; /* size of immediate data area */
|
||||||
int32_t vs_ndaddr; /* number of direct extentes */
|
__fs32 vs_ndaddr; /* number of direct extentes */
|
||||||
vx_daddr_t vs_firstau; /* address of first AU */
|
__fs32 vs_firstau; /* address of first AU */
|
||||||
vx_daddr_t vs_emap; /* offset of extent map in AU */
|
__fs32 vs_emap; /* offset of extent map in AU */
|
||||||
vx_daddr_t vs_imap; /* offset of inode map in AU */
|
__fs32 vs_imap; /* offset of inode map in AU */
|
||||||
vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */
|
__fs32 vs_iextop; /* offset of ExtOp. map in AU */
|
||||||
vx_daddr_t vs_istart; /* offset of inode list in AU */
|
__fs32 vs_istart; /* offset of inode list in AU */
|
||||||
vx_daddr_t vs_bstart; /* offset of fdblock in AU */
|
__fs32 vs_bstart; /* offset of fdblock in AU */
|
||||||
vx_daddr_t vs_femap; /* aufirst + emap */
|
__fs32 vs_femap; /* aufirst + emap */
|
||||||
vx_daddr_t vs_fimap; /* aufirst + imap */
|
__fs32 vs_fimap; /* aufirst + imap */
|
||||||
vx_daddr_t vs_fiextop; /* aufirst + iextop */
|
__fs32 vs_fiextop; /* aufirst + iextop */
|
||||||
vx_daddr_t vs_fistart; /* aufirst + istart */
|
__fs32 vs_fistart; /* aufirst + istart */
|
||||||
vx_daddr_t vs_fbstart; /* aufirst + bstart */
|
__fs32 vs_fbstart; /* aufirst + bstart */
|
||||||
int32_t vs_nindir; /* number of entries in indir */
|
__fs32 vs_nindir; /* number of entries in indir */
|
||||||
int32_t vs_aulen; /* length of AU in blocks */
|
__fs32 vs_aulen; /* length of AU in blocks */
|
||||||
int32_t vs_auimlen; /* length of imap in blocks */
|
__fs32 vs_auimlen; /* length of imap in blocks */
|
||||||
int32_t vs_auemlen; /* length of emap in blocks */
|
__fs32 vs_auemlen; /* length of emap in blocks */
|
||||||
int32_t vs_auilen; /* length of ilist in blocks */
|
__fs32 vs_auilen; /* length of ilist in blocks */
|
||||||
int32_t vs_aupad; /* length of pad in blocks */
|
__fs32 vs_aupad; /* length of pad in blocks */
|
||||||
int32_t vs_aublocks; /* data blocks in AU */
|
__fs32 vs_aublocks; /* data blocks in AU */
|
||||||
int32_t vs_maxtier; /* log base 2 of aublocks */
|
__fs32 vs_maxtier; /* log base 2 of aublocks */
|
||||||
int32_t vs_inopb; /* number of inodes per blk */
|
__fs32 vs_inopb; /* number of inodes per blk */
|
||||||
int32_t vs_old_inopau; /* obsolete */
|
__fs32 vs_old_inopau; /* obsolete */
|
||||||
int32_t vs_old_inopilb; /* obsolete */
|
__fs32 vs_old_inopilb; /* obsolete */
|
||||||
int32_t vs_old_ndiripau; /* obsolete */
|
__fs32 vs_old_ndiripau; /* obsolete */
|
||||||
int32_t vs_iaddrlen; /* size of indirect addr ext. */
|
__fs32 vs_iaddrlen; /* size of indirect addr ext. */
|
||||||
int32_t vs_bshift; /* log base 2 of bsize */
|
__fs32 vs_bshift; /* log base 2 of bsize */
|
||||||
int32_t vs_inoshift; /* log base 2 of inobp */
|
__fs32 vs_inoshift; /* log base 2 of inobp */
|
||||||
int32_t vs_bmask; /* ~( bsize - 1 ) */
|
__fs32 vs_bmask; /* ~( bsize - 1 ) */
|
||||||
int32_t vs_boffmask; /* bsize - 1 */
|
__fs32 vs_boffmask; /* bsize - 1 */
|
||||||
int32_t vs_old_inomask; /* old_inopilb - 1 */
|
__fs32 vs_old_inomask; /* old_inopilb - 1 */
|
||||||
int32_t vs_checksum; /* checksum of V1 data */
|
__fs32 vs_checksum; /* checksum of V1 data */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Version 1, writable
|
* Version 1, writable
|
||||||
*/
|
*/
|
||||||
int32_t vs_free; /* number of free blocks */
|
__fs32 vs_free; /* number of free blocks */
|
||||||
int32_t vs_ifree; /* number of free inodes */
|
__fs32 vs_ifree; /* number of free inodes */
|
||||||
int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */
|
__fs32 vs_efree[VXFS_NEFREE]; /* number of free extents by size */
|
||||||
int32_t vs_flags; /* flags ?!? */
|
__fs32 vs_flags; /* flags ?!? */
|
||||||
u_int8_t vs_mod; /* filesystem has been changed */
|
__u8 vs_mod; /* filesystem has been changed */
|
||||||
u_int8_t vs_clean; /* clean FS */
|
__u8 vs_clean; /* clean FS */
|
||||||
u_int16_t __unused4; /* unused */
|
__fs16 __unused4; /* unused */
|
||||||
u_int32_t vs_firstlogid; /* mount time log ID */
|
__fs32 vs_firstlogid; /* mount time log ID */
|
||||||
u_int32_t vs_wtime; /* last time written - sec */
|
__fs32 vs_wtime; /* last time written - sec */
|
||||||
u_int32_t vs_wutime; /* last time written - usec */
|
__fs32 vs_wutime; /* last time written - usec */
|
||||||
u_int8_t vs_fname[6]; /* FS name */
|
__u8 vs_fname[6]; /* FS name */
|
||||||
u_int8_t vs_fpack[6]; /* FS pack name */
|
__u8 vs_fpack[6]; /* FS pack name */
|
||||||
int32_t vs_logversion; /* log format version */
|
__fs32 vs_logversion; /* log format version */
|
||||||
int32_t __unused5; /* unused */
|
__u32 __unused5; /* unused */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Version 2, Read-only
|
* Version 2, Read-only
|
||||||
*/
|
*/
|
||||||
vx_daddr_t vs_oltext[2]; /* OLT extent and replica */
|
__fs32 vs_oltext[2]; /* OLT extent and replica */
|
||||||
int32_t vs_oltsize; /* OLT extent size */
|
__fs32 vs_oltsize; /* OLT extent size */
|
||||||
int32_t vs_iauimlen; /* size of inode map */
|
__fs32 vs_iauimlen; /* size of inode map */
|
||||||
int32_t vs_iausize; /* size of IAU in blocks */
|
__fs32 vs_iausize; /* size of IAU in blocks */
|
||||||
int32_t vs_dinosize; /* size of inode in bytes */
|
__fs32 vs_dinosize; /* size of inode in bytes */
|
||||||
int32_t vs_old_dniaddr; /* indir levels per inode */
|
__fs32 vs_old_dniaddr; /* indir levels per inode */
|
||||||
int32_t vs_checksum2; /* checksum of V2 RO */
|
__fs32 vs_checksum2; /* checksum of V2 RO */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually much more...
|
* Actually much more...
|
||||||
@ -168,8 +170,32 @@ struct vxfs_sb_info {
|
|||||||
ino_t vsi_fshino; /* fileset header inode */
|
ino_t vsi_fshino; /* fileset header inode */
|
||||||
daddr_t vsi_oltext; /* OLT extent */
|
daddr_t vsi_oltext; /* OLT extent */
|
||||||
daddr_t vsi_oltsize; /* OLT size */
|
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
|
* 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_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
|
||||||
#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
|
#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.
|
* Get filesystem private data from VFS superblock.
|
||||||
*/
|
*/
|
||||||
|
@ -68,8 +68,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
|
|||||||
{
|
{
|
||||||
struct super_block *sb = ip->i_sb;
|
struct super_block *sb = ip->i_sb;
|
||||||
struct vxfs_inode_info *vip = VXFS_INO(ip);
|
struct vxfs_inode_info *vip = VXFS_INO(ip);
|
||||||
|
struct vxfs_sb_info *sbi = VXFS_SBI(sb);
|
||||||
unsigned long bsize = sb->s_blocksize;
|
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;
|
int i;
|
||||||
|
|
||||||
if (indsize > sb->s_blocksize)
|
if (indsize > sb->s_blocksize)
|
||||||
@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
|
|||||||
|
|
||||||
for (i = 0; i < VXFS_NDADDR; i++) {
|
for (i = 0; i < VXFS_NDADDR; i++) {
|
||||||
struct direct *d = vip->vii_ext4.ve4_direct + i;
|
struct direct *d = vip->vii_ext4.ve4_direct + i;
|
||||||
if (bn >= 0 && bn < d->size)
|
if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
|
||||||
return (bn + d->extent);
|
return (bn + fs32_to_cpu(sbi, d->extent));
|
||||||
bn -= d->size;
|
bn -= fs32_to_cpu(sbi, d->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bn / (indsize * indsize * bsize / 4)) == 0) {
|
if ((bn / (indsize * indsize * bsize / 4)) == 0) {
|
||||||
struct buffer_head *buf;
|
struct buffer_head *buf;
|
||||||
daddr_t bno;
|
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))
|
if (!buf || !buffer_mapped(buf))
|
||||||
goto fail_buf;
|
goto fail_buf;
|
||||||
|
|
||||||
indir = (u32 *)buf->b_data;
|
indir = (__fs32 *)buf->b_data;
|
||||||
bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
|
bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
|
||||||
|
(bn % indsize);
|
||||||
|
|
||||||
brelse(buf);
|
brelse(buf);
|
||||||
return bno;
|
return bno;
|
||||||
@ -127,6 +130,7 @@ fail_buf:
|
|||||||
static daddr_t
|
static daddr_t
|
||||||
vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
|
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;
|
struct buffer_head *bp = NULL;
|
||||||
daddr_t pblock = 0;
|
daddr_t pblock = 0;
|
||||||
int i;
|
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) +
|
typ = ((struct vxfs_typed *)bp->b_data) +
|
||||||
(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
|
(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) {
|
if (block < off) {
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
continue;
|
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:
|
case VXFS_TYPED_INDIRECT:
|
||||||
pblock = vxfs_bmap_indir(ip, typ->vt_block,
|
pblock = vxfs_bmap_indir(ip,
|
||||||
typ->vt_size, block - off);
|
fs32_to_cpu(sbi, typ->vt_block),
|
||||||
|
fs32_to_cpu(sbi, typ->vt_size),
|
||||||
|
block - off);
|
||||||
if (pblock == -2)
|
if (pblock == -2)
|
||||||
break;
|
break;
|
||||||
goto out;
|
goto out;
|
||||||
case VXFS_TYPED_DATA:
|
case VXFS_TYPED_DATA:
|
||||||
if ((block - off) >= typ->vt_size)
|
if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
|
||||||
break;
|
break;
|
||||||
pblock = (typ->vt_block + block - off);
|
pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
|
||||||
goto out;
|
goto out;
|
||||||
case VXFS_TYPED_INDIRECT_DEV4:
|
case VXFS_TYPED_INDIRECT_DEV4:
|
||||||
case VXFS_TYPED_DATA_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;
|
(struct vxfs_typed_dev4 *)typ;
|
||||||
|
|
||||||
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
|
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
|
||||||
printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
|
printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
|
||||||
(unsigned long long) typ4->vd4_block,
|
fs64_to_cpu(sbi, typ4->vd4_block),
|
||||||
(unsigned long long) typ4->vd4_size,
|
fs64_to_cpu(sbi, typ4->vd4_size),
|
||||||
typ4->vd4_dev);
|
fs32_to_cpu(sbi, typ4->vd4_dev));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
|
||||||
|
__LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
@ -201,28 +210,33 @@ static daddr_t
|
|||||||
vxfs_bmap_typed(struct inode *ip, long iblock)
|
vxfs_bmap_typed(struct inode *ip, long iblock)
|
||||||
{
|
{
|
||||||
struct vxfs_inode_info *vip = VXFS_INO(ip);
|
struct vxfs_inode_info *vip = VXFS_INO(ip);
|
||||||
|
struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
|
||||||
daddr_t pblock = 0;
|
daddr_t pblock = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < VXFS_NTYPED; i++) {
|
for (i = 0; i < VXFS_NTYPED; i++) {
|
||||||
struct vxfs_typed *typ = vip->vii_org.typed + 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
|
#ifdef DIAGNOSTIC
|
||||||
vxfs_typdump(typ);
|
vxfs_typdump(typ);
|
||||||
#endif
|
#endif
|
||||||
if (iblock < off)
|
if (iblock < off)
|
||||||
continue;
|
continue;
|
||||||
switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
|
switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
|
||||||
case VXFS_TYPED_INDIRECT:
|
case VXFS_TYPED_INDIRECT:
|
||||||
pblock = vxfs_bmap_indir(ip, typ->vt_block,
|
pblock = vxfs_bmap_indir(ip,
|
||||||
typ->vt_size, iblock - off);
|
fs32_to_cpu(sbi, typ->vt_block),
|
||||||
|
fs32_to_cpu(sbi, typ->vt_size),
|
||||||
|
iblock - off);
|
||||||
if (pblock == -2)
|
if (pblock == -2)
|
||||||
break;
|
break;
|
||||||
return (pblock);
|
return (pblock);
|
||||||
case VXFS_TYPED_DATA:
|
case VXFS_TYPED_DATA:
|
||||||
if ((iblock - off) < typ->vt_size)
|
if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
|
||||||
return (typ->vt_block + iblock - off);
|
return (fs32_to_cpu(sbi, typ->vt_block) +
|
||||||
|
iblock - off);
|
||||||
break;
|
break;
|
||||||
case VXFS_TYPED_INDIRECT_DEV4:
|
case VXFS_TYPED_INDIRECT_DEV4:
|
||||||
case VXFS_TYPED_DATA_DEV4: {
|
case VXFS_TYPED_DATA_DEV4: {
|
||||||
@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
|
|||||||
(struct vxfs_typed_dev4 *)typ;
|
(struct vxfs_typed_dev4 *)typ;
|
||||||
|
|
||||||
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
|
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
|
||||||
printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
|
printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
|
||||||
(unsigned long long) typ4->vd4_block,
|
fs64_to_cpu(sbi, typ4->vd4_block),
|
||||||
(unsigned long long) typ4->vd4_size,
|
fs64_to_cpu(sbi, typ4->vd4_size),
|
||||||
typ4->vd4_dev);
|
fs32_to_cpu(sbi, typ4->vd4_dev));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -48,9 +48,9 @@
|
|||||||
* Linux driver for now.
|
* Linux driver for now.
|
||||||
*/
|
*/
|
||||||
struct vxfs_dirblk {
|
struct vxfs_dirblk {
|
||||||
u_int16_t d_free; /* free space in dirblock */
|
__fs16 d_free; /* free space in dirblock */
|
||||||
u_int16_t d_nhash; /* no of hash chains */
|
__fs16 d_nhash; /* no of hash chains */
|
||||||
u_int16_t d_hash[1]; /* hash chain */
|
__fs16 d_hash[1]; /* hash chain */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -63,10 +63,10 @@ struct vxfs_dirblk {
|
|||||||
* VxFS directory entry.
|
* VxFS directory entry.
|
||||||
*/
|
*/
|
||||||
struct vxfs_direct {
|
struct vxfs_direct {
|
||||||
vx_ino_t d_ino; /* inode number */
|
__fs32 d_ino; /* inode number */
|
||||||
u_int16_t d_reclen; /* record length */
|
__fs16 d_reclen; /* record length */
|
||||||
u_int16_t d_namelen; /* d_name length */
|
__fs16 d_namelen; /* d_name length */
|
||||||
u_int16_t d_hashnext; /* next hash entry */
|
__fs16 d_hashnext; /* next hash entry */
|
||||||
char d_name[VXFS_NAMELEN]; /* name */
|
char d_name[VXFS_NAMELEN]; /* name */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,6 +87,7 @@ struct vxfs_direct {
|
|||||||
/*
|
/*
|
||||||
* VXFS_DIRBLKOV is the overhead of a specific dirblock.
|
* 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_ */
|
#endif /* _VXFS_DIR_H_ */
|
||||||
|
@ -52,14 +52,10 @@ extern int vxfs_read_fshead(struct super_block *);
|
|||||||
|
|
||||||
/* vxfs_inode.c */
|
/* vxfs_inode.c */
|
||||||
extern const struct address_space_operations vxfs_immed_aops;
|
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 void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
|
||||||
extern struct inode * vxfs_get_fake_inode(struct super_block *,
|
extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
|
||||||
struct vxfs_inode_info *);
|
extern struct inode *vxfs_stiget(struct super_block *, ino_t);
|
||||||
extern void vxfs_put_fake_inode(struct inode *);
|
extern struct inode *vxfs_iget(struct super_block *, ino_t);
|
||||||
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 void vxfs_evict_inode(struct inode *);
|
extern void vxfs_evict_inode(struct inode *);
|
||||||
|
|
||||||
/* vxfs_lookup.c */
|
/* vxfs_lookup.c */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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_sb_info *infp = VXFS_SBI(sbp);
|
||||||
struct vxfs_fsh *pfp, *sfp;
|
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);
|
infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
|
||||||
if (!vip) {
|
if (!infp->vsi_fship) {
|
||||||
printk(KERN_ERR "vxfs: unable to read fsh inode\n");
|
printk(KERN_ERR "vxfs: unable to read fsh inode\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vip = VXFS_INO(infp->vsi_fship);
|
||||||
if (!VXFS_ISFSH(vip)) {
|
if (!VXFS_ISFSH(vip)) {
|
||||||
printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
|
printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
|
||||||
vip->vii_mode & VXFS_TYPE_MASK);
|
vip->vii_mode & VXFS_TYPE_MASK);
|
||||||
goto out_free_fship;
|
goto out_iput_fship;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
printk("vxfs: fsh inode dump:\n");
|
printk("vxfs: fsh inode dump:\n");
|
||||||
vxfs_dumpi(vip, infp->vsi_fshino);
|
vxfs_dumpi(vip, infp->vsi_fshino);
|
||||||
#endif
|
#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);
|
sfp = vxfs_getfsh(infp->vsi_fship, 0);
|
||||||
if (!sfp) {
|
if (!sfp) {
|
||||||
printk(KERN_ERR "vxfs: unable to get structural fsh\n");
|
printk(KERN_ERR "vxfs: unable to get structural fsh\n");
|
||||||
@ -153,14 +149,10 @@ vxfs_read_fshead(struct super_block *sbp)
|
|||||||
vxfs_dumpfsh(pfp);
|
vxfs_dumpfsh(pfp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
|
infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext,
|
||||||
if (!tip)
|
fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
|
||||||
goto out_free_pfp;
|
|
||||||
|
|
||||||
infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
|
|
||||||
if (!infp->vsi_stilist) {
|
if (!infp->vsi_stilist) {
|
||||||
printk(KERN_ERR "vxfs: unable to get structural list inode\n");
|
printk(KERN_ERR "vxfs: unable to get structural list inode\n");
|
||||||
kfree(tip);
|
|
||||||
goto out_free_pfp;
|
goto out_free_pfp;
|
||||||
}
|
}
|
||||||
if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
|
if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
|
||||||
@ -169,13 +161,9 @@ vxfs_read_fshead(struct super_block *sbp)
|
|||||||
goto out_iput_stilist;
|
goto out_iput_stilist;
|
||||||
}
|
}
|
||||||
|
|
||||||
tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
|
infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
|
||||||
if (!tip)
|
|
||||||
goto out_iput_stilist;
|
|
||||||
infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
|
|
||||||
if (!infp->vsi_ilist) {
|
if (!infp->vsi_ilist) {
|
||||||
printk(KERN_ERR "vxfs: unable to get inode list inode\n");
|
printk(KERN_ERR "vxfs: unable to get inode list inode\n");
|
||||||
kfree(tip);
|
|
||||||
goto out_iput_stilist;
|
goto out_iput_stilist;
|
||||||
}
|
}
|
||||||
if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
|
if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
|
||||||
@ -184,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp)
|
|||||||
goto out_iput_ilist;
|
goto out_iput_ilist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(pfp);
|
||||||
|
kfree(sfp);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_iput_ilist:
|
out_iput_ilist:
|
||||||
@ -197,7 +187,4 @@ vxfs_read_fshead(struct super_block *sbp)
|
|||||||
out_iput_fship:
|
out_iput_fship:
|
||||||
iput(infp->vsi_fship);
|
iput(infp->vsi_fship);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
out_free_fship:
|
|
||||||
kfree(vip);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,20 +43,20 @@
|
|||||||
* Fileset header
|
* Fileset header
|
||||||
*/
|
*/
|
||||||
struct vxfs_fsh {
|
struct vxfs_fsh {
|
||||||
u_int32_t fsh_version; /* fileset header version */
|
__fs32 fsh_version; /* fileset header version */
|
||||||
u_int32_t fsh_fsindex; /* fileset index */
|
__fs32 fsh_fsindex; /* fileset index */
|
||||||
u_int32_t fsh_time; /* modification time - sec */
|
__fs32 fsh_time; /* modification time - sec */
|
||||||
u_int32_t fsh_utime; /* modification time - usec */
|
__fs32 fsh_utime; /* modification time - usec */
|
||||||
u_int32_t fsh_extop; /* extop flags */
|
__fs32 fsh_extop; /* extop flags */
|
||||||
vx_ino_t fsh_ninodes; /* allocated inodes */
|
__fs32 fsh_ninodes; /* allocated inodes */
|
||||||
u_int32_t fsh_nau; /* number of IAUs */
|
__fs32 fsh_nau; /* number of IAUs */
|
||||||
u_int32_t fsh_old_ilesize; /* old size of ilist */
|
__fs32 fsh_old_ilesize; /* old size of ilist */
|
||||||
u_int32_t fsh_dflags; /* flags */
|
__fs32 fsh_dflags; /* flags */
|
||||||
u_int32_t fsh_quota; /* quota limit */
|
__fs32 fsh_quota; /* quota limit */
|
||||||
vx_ino_t fsh_maxinode; /* maximum inode number */
|
__fs32 fsh_maxinode; /* maximum inode number */
|
||||||
vx_ino_t fsh_iauino; /* IAU inode */
|
__fs32 fsh_iauino; /* IAU inode */
|
||||||
vx_ino_t fsh_ilistino[2]; /* ilist inodes */
|
__fs32 fsh_ilistino[2]; /* ilist inodes */
|
||||||
vx_ino_t fsh_lctino; /* link count table inode */
|
__fs32 fsh_lctino; /* link count table inode */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Slightly more fields follow, but they
|
* Slightly more fields follow, but they
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -42,9 +43,6 @@
|
|||||||
#include "vxfs_extern.h"
|
#include "vxfs_extern.h"
|
||||||
|
|
||||||
|
|
||||||
struct kmem_cache *vxfs_inode_cachep;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
/*
|
/*
|
||||||
* Dump inode contents (partially).
|
* Dump inode contents (partially).
|
||||||
@ -68,118 +66,6 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* vxfs_blkiget - find inode based on extent #
|
|
||||||
* @sbp: superblock of the filesystem we search in
|
|
||||||
* @extent: number of the extent to search
|
|
||||||
* @ino: inode number to search
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* vxfs_blkiget searches inode @ino in the filesystem described by
|
|
||||||
* @sbp in the extent @extent.
|
|
||||||
* Returns the matching VxFS inode on success, else a NULL pointer.
|
|
||||||
*
|
|
||||||
* NOTE:
|
|
||||||
* While __vxfs_iget uses the pagecache vxfs_blkiget uses the
|
|
||||||
* buffercache. This function should not be used outside the
|
|
||||||
* read_super() method, otherwise the data may be incoherent.
|
|
||||||
*/
|
|
||||||
struct vxfs_inode_info *
|
|
||||||
vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
|
|
||||||
{
|
|
||||||
struct buffer_head *bp;
|
|
||||||
u_long block, offset;
|
|
||||||
|
|
||||||
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_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));
|
|
||||||
#ifdef DIAGNOSTIC
|
|
||||||
vxfs_dumpi(vip, ino);
|
|
||||||
#endif
|
|
||||||
brelse(bp);
|
|
||||||
return (vip);
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
|
||||||
printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
|
|
||||||
brelse(bp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __vxfs_iget - generic find inode facility
|
|
||||||
* @sbp: VFS superblock
|
|
||||||
* @ino: inode number
|
|
||||||
* @ilistp: inode list
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static struct vxfs_inode_info *
|
|
||||||
__vxfs_iget(ino_t ino, struct inode *ilistp)
|
|
||||||
{
|
|
||||||
struct page *pp;
|
|
||||||
u_long offset;
|
|
||||||
|
|
||||||
offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
|
|
||||||
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));
|
|
||||||
#ifdef DIAGNOSTIC
|
|
||||||
vxfs_dumpi(vip, ino);
|
|
||||||
#endif
|
|
||||||
vxfs_put_page(pp);
|
|
||||||
return (vip);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* vxfs_stiget - find inode using the structural inode list
|
|
||||||
* @sbp: VFS superblock
|
|
||||||
* @ino: inode #
|
|
||||||
*
|
|
||||||
* 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
|
* vxfs_transmod - mode for a VxFS inode
|
||||||
* @vip: VxFS inode
|
* @vip: VxFS inode
|
||||||
@ -211,74 +97,172 @@ vxfs_transmod(struct vxfs_inode_info *vip)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
|
||||||
* vxfs_iinit- helper to fill inode fields
|
struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
|
||||||
* @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)
|
|
||||||
{
|
{
|
||||||
|
struct inode *inode = &vip->vfs_inode;
|
||||||
|
|
||||||
ip->i_mode = vxfs_transmod(vip);
|
vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode);
|
||||||
i_uid_write(ip, (uid_t)vip->vii_uid);
|
vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink);
|
||||||
i_gid_write(ip, (gid_t)vip->vii_gid);
|
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;
|
||||||
|
|
||||||
set_nlink(ip, vip->vii_nlink);
|
vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks);
|
||||||
ip->i_size = vip->vii_size;
|
vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen);
|
||||||
|
|
||||||
ip->i_atime.tv_sec = vip->vii_atime;
|
if (VXFS_ISDIR(vip))
|
||||||
ip->i_ctime.tv_sec = vip->vii_ctime;
|
vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot);
|
||||||
ip->i_mtime.tv_sec = vip->vii_mtime;
|
else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip))
|
||||||
ip->i_atime.tv_nsec = 0;
|
vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev);
|
||||||
ip->i_ctime.tv_nsec = 0;
|
|
||||||
ip->i_mtime.tv_nsec = 0;
|
|
||||||
|
|
||||||
ip->i_blocks = vip->vii_blocks;
|
/* don't endian swap the fields that differ by orgtype */
|
||||||
ip->i_generation = vip->vii_gen;
|
memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org));
|
||||||
|
|
||||||
ip->i_private = vip;
|
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_get_fake_inode - get fake inode structure
|
* vxfs_blkiget - find inode based on extent #
|
||||||
* @sbp: filesystem superblock
|
* @sbp: superblock of the filesystem we search in
|
||||||
* @vip: fspriv inode
|
* @extent: number of the extent to search
|
||||||
|
* @ino: inode number to search
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* vxfs_fake_inode gets a fake inode (not in the inode hash) for a
|
* vxfs_blkiget searches inode @ino in the filesystem described by
|
||||||
* superblock, vxfs_inode pair.
|
* @sbp in the extent @extent.
|
||||||
* Returns the filled VFS inode.
|
* Returns the matching VxFS inode on success, else a NULL pointer.
|
||||||
|
*
|
||||||
|
* NOTE:
|
||||||
|
* While __vxfs_iget uses the pagecache vxfs_blkiget uses the
|
||||||
|
* buffercache. This function should not be used outside the
|
||||||
|
* read_super() method, otherwise the data may be incoherent.
|
||||||
*/
|
*/
|
||||||
struct inode *
|
struct inode *
|
||||||
vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
|
vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
|
||||||
{
|
{
|
||||||
struct inode *ip = NULL;
|
struct buffer_head *bp;
|
||||||
|
struct inode *inode;
|
||||||
|
u_long block, offset;
|
||||||
|
|
||||||
if ((ip = new_inode(sbp))) {
|
inode = new_inode(sbp);
|
||||||
ip->i_ino = get_next_ino();
|
if (!inode)
|
||||||
vxfs_iinit(ip, vip);
|
return NULL;
|
||||||
ip->i_mapping->a_ops = &vxfs_aops;
|
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 = VXFS_INO(inode);
|
||||||
|
struct vxfs_dinode *dip;
|
||||||
|
|
||||||
|
dip = (struct vxfs_dinode *)(bp->b_data + offset);
|
||||||
|
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 inode;
|
||||||
}
|
}
|
||||||
return (ip);
|
|
||||||
|
printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
|
||||||
|
brelse(bp);
|
||||||
|
iput(inode);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vxfs_put_fake_inode - free faked inode
|
* __vxfs_iget - generic find inode facility
|
||||||
* *ip: VFS inode
|
* @ilistp: inode list
|
||||||
|
* @vip: VxFS inode to fill in
|
||||||
|
* @ino: inode number
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* vxfs_put_fake_inode frees all data associated with @ip.
|
* Search the for inode number @ino in the filesystem
|
||||||
|
* described by @sbp. Use the specified inode table (@ilistp).
|
||||||
|
* Returns the matching inode on success, else an error code.
|
||||||
*/
|
*/
|
||||||
void
|
static int
|
||||||
vxfs_put_fake_inode(struct inode *ip)
|
__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino)
|
||||||
{
|
{
|
||||||
iput(ip);
|
struct page *pp;
|
||||||
|
u_long offset;
|
||||||
|
|
||||||
|
offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
|
||||||
|
pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
|
||||||
|
|
||||||
|
if (!IS_ERR(pp)) {
|
||||||
|
struct vxfs_dinode *dip;
|
||||||
|
caddr_t kaddr = (char *)page_address(pp);
|
||||||
|
|
||||||
|
dip = (struct vxfs_dinode *)(kaddr + offset);
|
||||||
|
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 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n",
|
||||||
|
pp, (unsigned long)ino);
|
||||||
|
return PTR_ERR(pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vxfs_stiget - find inode using the structural inode list
|
||||||
|
* @sbp: VFS superblock
|
||||||
|
* @ino: inode #
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Find inode @ino in the filesystem described by @sbp using
|
||||||
|
* the structural inode list.
|
||||||
|
* Returns the matching inode on success, else a NULL pointer.
|
||||||
|
*/
|
||||||
|
struct inode *
|
||||||
|
vxfs_stiget(struct super_block *sbp, ino_t ino)
|
||||||
|
{
|
||||||
|
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 inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,6 +280,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
|
|||||||
struct vxfs_inode_info *vip;
|
struct vxfs_inode_info *vip;
|
||||||
const struct address_space_operations *aops;
|
const struct address_space_operations *aops;
|
||||||
struct inode *ip;
|
struct inode *ip;
|
||||||
|
int error;
|
||||||
|
|
||||||
ip = iget_locked(sbp, ino);
|
ip = iget_locked(sbp, ino);
|
||||||
if (!ip)
|
if (!ip)
|
||||||
@ -303,14 +288,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
|
|||||||
if (!(ip->i_state & I_NEW))
|
if (!(ip->i_state & I_NEW))
|
||||||
return ip;
|
return ip;
|
||||||
|
|
||||||
vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
|
vip = VXFS_INO(ip);
|
||||||
if (IS_ERR(vip)) {
|
error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino);
|
||||||
|
if (error) {
|
||||||
iget_failed(ip);
|
iget_failed(ip);
|
||||||
return ERR_CAST(vip);
|
return ERR_PTR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
vxfs_iinit(ip, vip);
|
|
||||||
|
|
||||||
if (VXFS_ISIMMED(vip))
|
if (VXFS_ISIMMED(vip))
|
||||||
aops = &vxfs_immed_aops;
|
aops = &vxfs_immed_aops;
|
||||||
else
|
else
|
||||||
@ -341,12 +325,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
|
|||||||
return ip;
|
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
|
* vxfs_evict_inode - remove inode from main memory
|
||||||
* @ip: inode to discard.
|
* @ip: inode to discard.
|
||||||
@ -360,5 +338,4 @@ vxfs_evict_inode(struct inode *ip)
|
|||||||
{
|
{
|
||||||
truncate_inode_pages_final(&ip->i_data);
|
truncate_inode_pages_final(&ip->i_data);
|
||||||
clear_inode(ip);
|
clear_inode(ip);
|
||||||
call_rcu(&ip->i_rcu, vxfs_i_callback);
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -66,74 +67,74 @@ enum {
|
|||||||
* Data stored immediately in the inode.
|
* Data stored immediately in the inode.
|
||||||
*/
|
*/
|
||||||
struct vxfs_immed {
|
struct vxfs_immed {
|
||||||
u_int8_t vi_immed[VXFS_NIMMED];
|
__u8 vi_immed[VXFS_NIMMED];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vxfs_ext4 {
|
struct vxfs_ext4 {
|
||||||
u_int32_t ve4_spare; /* ?? */
|
__fs32 ve4_spare; /* ?? */
|
||||||
u_int32_t ve4_indsize; /* Indirect extent size */
|
__fs32 ve4_indsize; /* Indirect extent size */
|
||||||
vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */
|
__fs32 ve4_indir[VXFS_NIADDR]; /* Indirect extents */
|
||||||
struct direct { /* Direct extents */
|
struct direct { /* Direct extents */
|
||||||
vx_daddr_t extent; /* Extent number */
|
__fs32 extent; /* Extent number */
|
||||||
int32_t size; /* Size of extent */
|
__fs32 size; /* Size of extent */
|
||||||
} ve4_direct[VXFS_NDADDR];
|
} ve4_direct[VXFS_NDADDR];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vxfs_typed {
|
struct vxfs_typed {
|
||||||
u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
|
__fs64 vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
|
||||||
vx_daddr_t vt_block; /* Extent block */
|
__fs32 vt_block; /* Extent block */
|
||||||
int32_t vt_size; /* Size in blocks */
|
__fs32 vt_size; /* Size in blocks */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vxfs_typed_dev4 {
|
struct vxfs_typed_dev4 {
|
||||||
u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
|
__fs64 vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
|
||||||
u_int64_t vd4_block; /* Extent block */
|
__fs64 vd4_block; /* Extent block */
|
||||||
u_int64_t vd4_size; /* Size in blocks */
|
__fs64 vd4_size; /* Size in blocks */
|
||||||
int32_t vd4_dev; /* Device ID */
|
__fs32 vd4_dev; /* Device ID */
|
||||||
u_int32_t __pad1;
|
__u8 __pad1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The inode as contained on the physical device.
|
* The inode as contained on the physical device.
|
||||||
*/
|
*/
|
||||||
struct vxfs_dinode {
|
struct vxfs_dinode {
|
||||||
int32_t vdi_mode;
|
__fs32 vdi_mode;
|
||||||
u_int32_t vdi_nlink; /* Link count */
|
__fs32 vdi_nlink; /* Link count */
|
||||||
u_int32_t vdi_uid; /* UID */
|
__fs32 vdi_uid; /* UID */
|
||||||
u_int32_t vdi_gid; /* GID */
|
__fs32 vdi_gid; /* GID */
|
||||||
u_int64_t vdi_size; /* Inode size in bytes */
|
__fs64 vdi_size; /* Inode size in bytes */
|
||||||
u_int32_t vdi_atime; /* Last time accessed - sec */
|
__fs32 vdi_atime; /* Last time accessed - sec */
|
||||||
u_int32_t vdi_autime; /* Last time accessed - usec */
|
__fs32 vdi_autime; /* Last time accessed - usec */
|
||||||
u_int32_t vdi_mtime; /* Last modify time - sec */
|
__fs32 vdi_mtime; /* Last modify time - sec */
|
||||||
u_int32_t vdi_mutime; /* Last modify time - usec */
|
__fs32 vdi_mutime; /* Last modify time - usec */
|
||||||
u_int32_t vdi_ctime; /* Create time - sec */
|
__fs32 vdi_ctime; /* Create time - sec */
|
||||||
u_int32_t vdi_cutime; /* Create time - usec */
|
__fs32 vdi_cutime; /* Create time - usec */
|
||||||
u_int8_t vdi_aflags; /* Allocation flags */
|
__u8 vdi_aflags; /* Allocation flags */
|
||||||
u_int8_t vdi_orgtype; /* Organisation type */
|
__u8 vdi_orgtype; /* Organisation type */
|
||||||
u_int16_t vdi_eopflags;
|
__fs16 vdi_eopflags;
|
||||||
u_int32_t vdi_eopdata;
|
__fs32 vdi_eopdata;
|
||||||
union {
|
union {
|
||||||
u_int32_t rdev;
|
__fs32 rdev;
|
||||||
u_int32_t dotdot;
|
__fs32 dotdot;
|
||||||
struct {
|
struct {
|
||||||
u_int32_t reserved;
|
__u32 reserved;
|
||||||
u_int32_t fixextsize;
|
__fs32 fixextsize;
|
||||||
} i_regular;
|
} i_regular;
|
||||||
struct {
|
struct {
|
||||||
u_int32_t matchino;
|
__fs32 matchino;
|
||||||
u_int32_t fsetindex;
|
__fs32 fsetindex;
|
||||||
} i_vxspec;
|
} i_vxspec;
|
||||||
u_int64_t align;
|
__u64 align;
|
||||||
} vdi_ftarea;
|
} vdi_ftarea;
|
||||||
u_int32_t vdi_blocks; /* How much blocks does inode occupy */
|
__fs32 vdi_blocks; /* How much blocks does inode occupy */
|
||||||
u_int32_t vdi_gen; /* Inode generation */
|
__fs32 vdi_gen; /* Inode generation */
|
||||||
u_int64_t vdi_version; /* Version */
|
__fs64 vdi_version; /* Version */
|
||||||
union {
|
union {
|
||||||
struct vxfs_immed immed;
|
struct vxfs_immed immed;
|
||||||
struct vxfs_ext4 ext4;
|
struct vxfs_ext4 ext4;
|
||||||
struct vxfs_typed typed[VXFS_NTYPED];
|
struct vxfs_typed typed[VXFS_NTYPED];
|
||||||
} vdi_org;
|
} vdi_org;
|
||||||
u_int32_t vdi_iattrino;
|
__fs32 vdi_iattrino;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define vdi_rdev vdi_ftarea.rdev
|
#define vdi_rdev vdi_ftarea.rdev
|
||||||
@ -149,32 +150,45 @@ struct vxfs_dinode {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The inode as represented in the main memory.
|
* The inode as represented in the main memory.
|
||||||
*
|
|
||||||
* TBD: This should become a separate structure...
|
|
||||||
*/
|
*/
|
||||||
#define vxfs_inode_info vxfs_dinode
|
struct vxfs_inode_info {
|
||||||
|
struct inode vfs_inode;
|
||||||
|
|
||||||
#define vii_mode vdi_mode
|
__u32 vii_mode;
|
||||||
#define vii_uid vdi_uid
|
__u32 vii_nlink; /* Link count */
|
||||||
#define vii_gid vdi_gid
|
__u32 vii_uid; /* UID */
|
||||||
#define vii_nlink vdi_nlink
|
__u32 vii_gid; /* GID */
|
||||||
#define vii_size vdi_size
|
__u64 vii_size; /* Inode size in bytes */
|
||||||
#define vii_atime vdi_atime
|
__u32 vii_atime; /* Last time accessed - sec */
|
||||||
#define vii_ctime vdi_ctime
|
__u32 vii_autime; /* Last time accessed - usec */
|
||||||
#define vii_mtime vdi_mtime
|
__u32 vii_mtime; /* Last modify time - sec */
|
||||||
#define vii_blocks vdi_blocks
|
__u32 vii_mutime; /* Last modify time - usec */
|
||||||
#define vii_org vdi_org
|
__u32 vii_ctime; /* Create time - sec */
|
||||||
#define vii_orgtype vdi_orgtype
|
__u32 vii_cutime; /* Create time - usec */
|
||||||
#define vii_gen vdi_gen
|
__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 vdi_ftarea.rdev
|
#define vii_rdev vii_ftarea.rdev
|
||||||
#define vii_dotdot vdi_ftarea.dotdot
|
#define vii_dotdot vii_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_immed vii_org.immed
|
||||||
#define vii_ext4 vdi_org.ext4
|
#define vii_ext4 vii_org.ext4
|
||||||
#define vii_typed vdi_org.typed
|
#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_ */
|
#endif /* _VXFS_INODE_H_ */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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,
|
.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
|
* 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 *
|
static struct vxfs_direct *
|
||||||
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
|
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;
|
||||||
u_long bsize = ip->i_sb->s_blocksize;
|
const char *name = dp->d_name.name;
|
||||||
const char *name = dp->d_name.name;
|
int namelen = dp->d_name.len;
|
||||||
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);
|
||||||
|
|
||||||
npages = dir_pages(ip);
|
while (pos < limit) {
|
||||||
nblocks = dir_blocks(ip);
|
struct page *pp;
|
||||||
pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
|
char *kaddr;
|
||||||
|
int pg_ofs = pos & ~PAGE_MASK;
|
||||||
for (page = 0; page < npages; page++) {
|
|
||||||
caddr_t kaddr;
|
|
||||||
struct page *pp;
|
|
||||||
|
|
||||||
pp = vxfs_get_page(ip->i_mapping, page);
|
pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
|
||||||
if (IS_ERR(pp))
|
if (IS_ERR(pp))
|
||||||
continue;
|
return NULL;
|
||||||
kaddr = (caddr_t)page_address(pp);
|
kaddr = (char *)page_address(pp);
|
||||||
|
|
||||||
for (block = 0; block <= nblocks && block <= pblocks; block++) {
|
while (pg_ofs < PAGE_SIZE && pos < limit) {
|
||||||
caddr_t baddr, limit;
|
struct vxfs_direct *de;
|
||||||
struct vxfs_dirblk *dbp;
|
|
||||||
struct vxfs_direct *de;
|
|
||||||
|
|
||||||
baddr = kaddr + (block * bsize);
|
if ((pos & (bsize - 1)) < 4) {
|
||||||
limit = baddr + bsize - VXFS_DIRLEN(1);
|
struct vxfs_dirblk *dbp =
|
||||||
|
(struct vxfs_dirblk *)
|
||||||
dbp = (struct vxfs_dirblk *)baddr;
|
(kaddr + (pos & ~PAGE_MASK));
|
||||||
de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
|
int overhead = VXFS_DIRBLKOV(sbi, dbp);
|
||||||
|
|
||||||
for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
|
pos += overhead;
|
||||||
if (!de->d_reclen)
|
pg_ofs += overhead;
|
||||||
break;
|
}
|
||||||
if (!de->d_ino)
|
de = (struct vxfs_direct *)(kaddr + pg_ofs);
|
||||||
continue;
|
|
||||||
if (vxfs_match(namelen, name, de)) {
|
if (!de->d_reclen) {
|
||||||
*ppp = pp;
|
pos += bsize - 1;
|
||||||
return (de);
|
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);
|
de = vxfs_find_entry(dip, dp, &pp);
|
||||||
if (de) {
|
if (de) {
|
||||||
ino = de->d_ino;
|
ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
|
||||||
kunmap(pp);
|
kunmap(pp);
|
||||||
put_page(pp);
|
put_page(pp);
|
||||||
}
|
}
|
||||||
@ -233,74 +221,80 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
|
|||||||
struct inode *ip = file_inode(fp);
|
struct inode *ip = file_inode(fp);
|
||||||
struct super_block *sbp = ip->i_sb;
|
struct super_block *sbp = ip->i_sb;
|
||||||
u_long bsize = sbp->s_blocksize;
|
u_long bsize = sbp->s_blocksize;
|
||||||
u_long page, npages, block, pblocks, nblocks, offset;
|
loff_t pos, limit;
|
||||||
loff_t pos;
|
struct vxfs_sb_info *sbi = VXFS_SBI(sbp);
|
||||||
|
|
||||||
if (ctx->pos == 0) {
|
if (ctx->pos == 0) {
|
||||||
if (!dir_emit_dot(fp, ctx))
|
if (!dir_emit_dot(fp, ctx))
|
||||||
return 0;
|
goto out;
|
||||||
ctx->pos = 1;
|
ctx->pos++;
|
||||||
}
|
}
|
||||||
if (ctx->pos == 1) {
|
if (ctx->pos == 1) {
|
||||||
if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
|
if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
|
||||||
return 0;
|
goto out;
|
||||||
ctx->pos = 2;
|
ctx->pos++;
|
||||||
}
|
}
|
||||||
pos = ctx->pos - 2;
|
|
||||||
|
|
||||||
if (pos > VXFS_DIRROUND(ip->i_size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
npages = dir_pages(ip);
|
limit = VXFS_DIRROUND(ip->i_size);
|
||||||
nblocks = dir_blocks(ip);
|
if (ctx->pos > limit)
|
||||||
pblocks = VXFS_BLOCK_PER_PAGE(sbp);
|
goto out;
|
||||||
|
|
||||||
page = pos >> PAGE_SHIFT;
|
pos = ctx->pos & ~3L;
|
||||||
offset = pos & ~PAGE_MASK;
|
|
||||||
block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
|
|
||||||
|
|
||||||
for (; page < npages; page++, block = 0) {
|
while (pos < limit) {
|
||||||
char *kaddr;
|
struct page *pp;
|
||||||
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))
|
if (IS_ERR(pp))
|
||||||
continue;
|
return -ENOMEM;
|
||||||
|
|
||||||
kaddr = (char *)page_address(pp);
|
kaddr = (char *)page_address(pp);
|
||||||
|
|
||||||
for (; block <= nblocks && block <= pblocks; block++) {
|
while (pg_ofs < PAGE_SIZE && pos < limit) {
|
||||||
char *baddr, *limit;
|
struct vxfs_direct *de;
|
||||||
struct vxfs_dirblk *dbp;
|
|
||||||
struct vxfs_direct *de;
|
|
||||||
|
|
||||||
baddr = kaddr + (block * bsize);
|
if ((pos & (bsize - 1)) < 4) {
|
||||||
limit = baddr + bsize - VXFS_DIRLEN(1);
|
struct vxfs_dirblk *dbp =
|
||||||
|
(struct vxfs_dirblk *)
|
||||||
dbp = (struct vxfs_dirblk *)baddr;
|
(kaddr + (pos & ~PAGE_MASK));
|
||||||
de = (struct vxfs_direct *)
|
int overhead = VXFS_DIRBLKOV(sbi, dbp);
|
||||||
(offset ?
|
|
||||||
(kaddr + offset) :
|
|
||||||
(baddr + VXFS_DIRBLKOV(dbp)));
|
|
||||||
|
|
||||||
for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
|
pos += overhead;
|
||||||
if (!de->d_reclen)
|
pg_ofs += overhead;
|
||||||
break;
|
}
|
||||||
if (!de->d_ino)
|
de = (struct vxfs_direct *)(kaddr + pg_ofs);
|
||||||
continue;
|
|
||||||
|
if (!de->d_reclen) {
|
||||||
offset = (char *)de - kaddr;
|
pos += bsize - 1;
|
||||||
ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
|
pos &= ~(bsize - 1);
|
||||||
if (!dir_emit(ctx, de->d_name, de->d_namelen,
|
break;
|
||||||
de->d_ino, DT_UNKNOWN)) {
|
}
|
||||||
vxfs_put_page(pp);
|
|
||||||
return 0;
|
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);
|
vxfs_put_page(pp);
|
||||||
offset = 0;
|
if (!rc)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
|
|
||||||
|
ctx->pos = pos | 2;
|
||||||
|
|
||||||
|
out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -43,14 +43,14 @@ static inline void
|
|||||||
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
|
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
|
||||||
{
|
{
|
||||||
BUG_ON(infp->vsi_fshino);
|
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
|
static inline void
|
||||||
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
|
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
|
||||||
{
|
{
|
||||||
BUG_ON(infp->vsi_iext);
|
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
|
static inline u_long
|
||||||
@ -81,13 +81,12 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
|
|||||||
struct vxfs_olt *op;
|
struct vxfs_olt *op;
|
||||||
char *oaddr, *eaddr;
|
char *oaddr, *eaddr;
|
||||||
|
|
||||||
|
|
||||||
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
|
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
|
||||||
if (!bp || !bp->b_data)
|
if (!bp || !bp->b_data)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
op = (struct vxfs_olt *)bp->b_data;
|
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");
|
printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -102,14 +101,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
|
|||||||
goto fail;
|
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);
|
eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
|
||||||
|
|
||||||
while (oaddr < eaddr) {
|
while (oaddr < eaddr) {
|
||||||
struct vxfs_oltcommon *ocp =
|
struct vxfs_oltcommon *ocp =
|
||||||
(struct vxfs_oltcommon *)oaddr;
|
(struct vxfs_oltcommon *)oaddr;
|
||||||
|
|
||||||
switch (ocp->olt_type) {
|
switch (fs32_to_cpu(infp, ocp->olt_type)) {
|
||||||
case VXFS_OLT_FSHEAD:
|
case VXFS_OLT_FSHEAD:
|
||||||
vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
|
vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
|
||||||
break;
|
break;
|
||||||
@ -118,11 +117,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
oaddr += ocp->olt_size;
|
oaddr += fs32_to_cpu(infp, ocp->olt_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
return 0;
|
return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
|
@ -63,83 +63,83 @@ enum {
|
|||||||
* the initial inode list, the fileset header or the device configuration.
|
* the initial inode list, the fileset header or the device configuration.
|
||||||
*/
|
*/
|
||||||
struct vxfs_olt {
|
struct vxfs_olt {
|
||||||
u_int32_t olt_magic; /* magic number */
|
__fs32 olt_magic; /* magic number */
|
||||||
u_int32_t olt_size; /* size of this entry */
|
__fs32 olt_size; /* size of this entry */
|
||||||
u_int32_t olt_checksum; /* checksum of extent */
|
__fs32 olt_checksum; /* checksum of extent */
|
||||||
u_int32_t __unused1; /* ??? */
|
__u32 __unused1; /* ??? */
|
||||||
u_int32_t olt_mtime; /* time of last mod. (sec) */
|
__fs32 olt_mtime; /* time of last mod. (sec) */
|
||||||
u_int32_t olt_mutime; /* time of last mod. (usec) */
|
__fs32 olt_mutime; /* time of last mod. (usec) */
|
||||||
u_int32_t olt_totfree; /* free space in OLT extent */
|
__fs32 olt_totfree; /* free space in OLT extent */
|
||||||
vx_daddr_t olt_extents[2]; /* addr of this extent, replica */
|
__fs32 olt_extents[2]; /* addr of this extent, replica */
|
||||||
u_int32_t olt_esize; /* size of this extent */
|
__fs32 olt_esize; /* size of this extent */
|
||||||
vx_daddr_t olt_next[2]; /* addr of next extent, replica */
|
__fs32 olt_next[2]; /* addr of next extent, replica */
|
||||||
u_int32_t olt_nsize; /* size of next extent */
|
__fs32 olt_nsize; /* size of next extent */
|
||||||
u_int32_t __unused2; /* align to 8 byte boundary */
|
__u32 __unused2; /* align to 8 byte boundary */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VxFS common OLT entry (on disk).
|
* VxFS common OLT entry (on disk).
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltcommon {
|
struct vxfs_oltcommon {
|
||||||
u_int32_t olt_type; /* type of this record */
|
__fs32 olt_type; /* type of this record */
|
||||||
u_int32_t olt_size; /* size of this record */
|
__fs32 olt_size; /* size of this record */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VxFS free OLT entry (on disk).
|
* VxFS free OLT entry (on disk).
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltfree {
|
struct vxfs_oltfree {
|
||||||
u_int32_t olt_type; /* type of this record */
|
__fs32 olt_type; /* type of this record */
|
||||||
u_int32_t olt_fsize; /* size of this free record */
|
__fs32 olt_fsize; /* size of this free record */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VxFS initial-inode list (on disk).
|
* VxFS initial-inode list (on disk).
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltilist {
|
struct vxfs_oltilist {
|
||||||
u_int32_t olt_type; /* type of this record */
|
__fs32 olt_type; /* type of this record */
|
||||||
u_int32_t olt_size; /* size of this record */
|
__fs32 olt_size; /* size of this record */
|
||||||
vx_ino_t olt_iext[2]; /* initial inode list, replica */
|
__fs32 olt_iext[2]; /* initial inode list, replica */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Current Usage Table
|
* Current Usage Table
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltcut {
|
struct vxfs_oltcut {
|
||||||
u_int32_t olt_type; /* type of this record */
|
__fs32 olt_type; /* type of this record */
|
||||||
u_int32_t olt_size; /* size of this record */
|
__fs32 olt_size; /* size of this record */
|
||||||
vx_ino_t olt_cutino; /* inode of current usage table */
|
__fs32 olt_cutino; /* inode of current usage table */
|
||||||
u_int32_t __pad; /* unused, 8 byte align */
|
__u8 __pad; /* unused, 8 byte align */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inodes containing Superblock, Intent log and OLTs
|
* Inodes containing Superblock, Intent log and OLTs
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltsb {
|
struct vxfs_oltsb {
|
||||||
u_int32_t olt_type; /* type of this record */
|
__fs32 olt_type; /* type of this record */
|
||||||
u_int32_t olt_size; /* size of this record */
|
__fs32 olt_size; /* size of this record */
|
||||||
vx_ino_t olt_sbino; /* inode of superblock file */
|
__fs32 olt_sbino; /* inode of superblock file */
|
||||||
u_int32_t __unused1; /* ??? */
|
__u32 __unused1; /* ??? */
|
||||||
vx_ino_t olt_logino[2]; /* inode of log file,replica */
|
__fs32 olt_logino[2]; /* inode of log file,replica */
|
||||||
vx_ino_t olt_oltino[2]; /* inode of OLT, replica */
|
__fs32 olt_oltino[2]; /* inode of OLT, replica */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inode containing device configuration + it's replica
|
* Inode containing device configuration + it's replica
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltdev {
|
struct vxfs_oltdev {
|
||||||
u_int32_t olt_type; /* type of this record */
|
__fs32 olt_type; /* type of this record */
|
||||||
u_int32_t olt_size; /* size of this record */
|
__fs32 olt_size; /* size of this record */
|
||||||
vx_ino_t olt_devino[2]; /* inode of device config files */
|
__fs32 olt_devino[2]; /* inode of device config files */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fileset header
|
* Fileset header
|
||||||
*/
|
*/
|
||||||
struct vxfs_oltfshead {
|
struct vxfs_oltfshead {
|
||||||
u_int32_t olt_type; /* type number */
|
__fs32 olt_type; /* type number */
|
||||||
u_int32_t olt_size; /* size of this record */
|
__fs32 olt_size; /* size of this record */
|
||||||
vx_ino_t olt_fsino[2]; /* inodes of fileset header */
|
__fs32 olt_fsino[2]; /* inodes of fileset header */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _VXFS_OLT_H_ */
|
#endif /* _VXFS_OLT_H_ */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2001 Christoph Hellwig.
|
* Copyright (c) 2000-2001 Christoph Hellwig.
|
||||||
|
* Copyright (c) 2016 Krzysztof Blaszkowski
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -48,22 +49,11 @@
|
|||||||
#include "vxfs_inode.h"
|
#include "vxfs_inode.h"
|
||||||
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Christoph Hellwig");
|
MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
|
||||||
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
|
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
|
||||||
|
static struct kmem_cache *vxfs_inode_cachep;
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vxfs_put_super - free superblock resources
|
* 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);
|
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
|
||||||
|
|
||||||
vxfs_put_fake_inode(infp->vsi_fship);
|
iput(infp->vsi_fship);
|
||||||
vxfs_put_fake_inode(infp->vsi_ilist);
|
iput(infp->vsi_ilist);
|
||||||
vxfs_put_fake_inode(infp->vsi_stilist);
|
iput(infp->vsi_stilist);
|
||||||
|
|
||||||
brelse(infp->vsi_bp);
|
brelse(infp->vsi_bp);
|
||||||
kfree(infp);
|
kfree(infp);
|
||||||
@ -109,14 +99,15 @@ static int
|
|||||||
vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
|
vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
|
||||||
{
|
{
|
||||||
struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb);
|
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_type = VXFS_SUPER_MAGIC;
|
||||||
bufp->f_bsize = dentry->d_sb->s_blocksize;
|
bufp->f_bsize = dentry->d_sb->s_blocksize;
|
||||||
bufp->f_blocks = infp->vsi_raw->vs_dsize;
|
bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
|
||||||
bufp->f_bfree = infp->vsi_raw->vs_free;
|
bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
|
||||||
bufp->f_bavail = 0;
|
bufp->f_bavail = 0;
|
||||||
bufp->f_files = 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;
|
bufp->f_namelen = VXFS_NAMELEN;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -129,6 +120,81 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
|
|||||||
return 0;
|
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
|
* vxfs_read_super - read superblock into memory and initialize filesystem
|
||||||
* @sbp: VFS superblock (to fill)
|
* @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_info *infp;
|
||||||
struct vxfs_sb *rsbp;
|
struct vxfs_sb *rsbp;
|
||||||
struct buffer_head *bp = NULL;
|
|
||||||
u_long bsize;
|
u_long bsize;
|
||||||
struct inode *root;
|
struct inode *root;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
u32 j;
|
||||||
|
|
||||||
sbp->s_flags |= MS_RDONLY;
|
sbp->s_flags |= MS_RDONLY;
|
||||||
|
|
||||||
@ -168,42 +234,43 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp = sb_bread(sbp, 1);
|
sbp->s_op = &vxfs_super_ops;
|
||||||
if (!bp || !buffer_mapped(bp)) {
|
sbp->s_fs_info = infp;
|
||||||
if (!silent) {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"vxfs: unable to read disk superblock\n");
|
|
||||||
}
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsbp = (struct vxfs_sb *)bp->b_data;
|
if (!vxfs_try_sb_magic(sbp, silent, 1,
|
||||||
if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
|
(__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)
|
if (!silent)
|
||||||
printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
|
printk(KERN_NOTICE "vxfs: can't find superblock.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
|
rsbp = infp->vsi_raw;
|
||||||
printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
|
j = fs32_to_cpu(infp, rsbp->vs_version);
|
||||||
rsbp->vs_version);
|
if ((j < 2 || j > 4) && !silent) {
|
||||||
|
printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
|
printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
|
||||||
printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
|
printk(KERN_DEBUG "vxfs: blocksize: %d\n",
|
||||||
|
fs32_to_cpu(infp, rsbp->vs_bsize));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sbp->s_magic = rsbp->vs_magic;
|
sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
|
||||||
sbp->s_fs_info = infp;
|
|
||||||
|
|
||||||
infp->vsi_raw = rsbp;
|
infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
|
||||||
infp->vsi_bp = bp;
|
infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
|
||||||
infp->vsi_oltext = rsbp->vs_oltext[0];
|
|
||||||
infp->vsi_oltsize = 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");
|
printk(KERN_WARNING "vxfs: unable to set final block size\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -218,7 +285,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sbp->s_op = &vxfs_super_ops;
|
|
||||||
root = vxfs_iget(sbp, VXFS_ROOT_INO);
|
root = vxfs_iget(sbp, VXFS_ROOT_INO);
|
||||||
if (IS_ERR(root)) {
|
if (IS_ERR(root)) {
|
||||||
ret = PTR_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;
|
return 0;
|
||||||
|
|
||||||
out_free_ilist:
|
out_free_ilist:
|
||||||
vxfs_put_fake_inode(infp->vsi_fship);
|
iput(infp->vsi_fship);
|
||||||
vxfs_put_fake_inode(infp->vsi_ilist);
|
iput(infp->vsi_ilist);
|
||||||
vxfs_put_fake_inode(infp->vsi_stilist);
|
iput(infp->vsi_stilist);
|
||||||
out:
|
out:
|
||||||
brelse(bp);
|
brelse(infp->vsi_bp);
|
||||||
kfree(infp);
|
kfree(infp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user