diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/freevxfs |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/freevxfs')
-rw-r--r-- | fs/freevxfs/Makefile | 8 | ||||
-rw-r--r-- | fs/freevxfs/vxfs.h | 264 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_bmap.c | 280 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_dir.h | 92 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_extern.h | 76 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_fshead.c | 202 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_fshead.h | 67 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_immed.c | 114 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.c | 351 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.h | 180 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_kcompat.h | 49 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_lookup.c | 328 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_olt.c | 132 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_olt.h | 145 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_subr.c | 190 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_super.c | 278 |
16 files changed, 2756 insertions, 0 deletions
diff --git a/fs/freevxfs/Makefile b/fs/freevxfs/Makefile new file mode 100644 index 00000000000..87ad097440d --- /dev/null +++ b/fs/freevxfs/Makefile @@ -0,0 +1,8 @@ +# +# VxFS Makefile +# + +obj-$(CONFIG_VXFS_FS) += freevxfs.o + +freevxfs-objs := vxfs_bmap.o vxfs_fshead.o vxfs_immed.o vxfs_inode.o \ + vxfs_lookup.o vxfs_olt.o vxfs_subr.o vxfs_super.o diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h new file mode 100644 index 00000000000..8da0252642a --- /dev/null +++ b/fs/freevxfs/vxfs.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2000-2001 Christoph Hellwig. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _VXFS_SUPER_H_ +#define _VXFS_SUPER_H_ + +/* + * Veritas filesystem driver - superblock structure. + * + * This file contains the definition of the disk and core + * superblocks of the Veritas Filesystem. + */ +#include <linux/types.h> +#include "vxfs_kcompat.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). + */ +#define VXFS_SUPER_MAGIC 0xa501FCF5 + +/* + * The root inode. + */ +#define VXFS_ROOT_INO 2 + +/* + * Num of entries in free extent array + */ +#define VXFS_NEFREE 32 + + +/* + * VxFS superblock (disk). + */ +struct vxfs_sb { + /* + * Readonly fields for the version 1 superblock. + * + * 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 */ + + /* + * 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 */ + + /* + * 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 */ + + /* + * Actually much more... + */ +}; + + +/* + * In core superblock filesystem private data for VxFS. + */ +struct vxfs_sb_info { + struct vxfs_sb *vsi_raw; /* raw (on disk) supeblock */ + struct buffer_head *vsi_bp; /* buffer for raw superblock*/ + struct inode *vsi_fship; /* fileset header inode */ + struct inode *vsi_ilist; /* inode list inode */ + struct inode *vsi_stilist; /* structual inode list inode */ + u_long vsi_iext; /* initial inode list */ + ino_t vsi_fshino; /* fileset header inode */ + daddr_t vsi_oltext; /* OLT extent */ + daddr_t vsi_oltsize; /* OLT size */ +}; + + +/* + * File modes. File types above 0xf000 are vxfs internal only, they should + * not be passed back to higher levels of the system. vxfs file types must + * never have one of the regular file type bits set. + */ +enum vxfs_mode { + VXFS_ISUID = 0x00000800, /* setuid */ + VXFS_ISGID = 0x00000400, /* setgid */ + VXFS_ISVTX = 0x00000200, /* sticky bit */ + VXFS_IREAD = 0x00000100, /* read */ + VXFS_IWRITE = 0x00000080, /* write */ + VXFS_IEXEC = 0x00000040, /* exec */ + + VXFS_IFIFO = 0x00001000, /* Named pipe */ + VXFS_IFCHR = 0x00002000, /* Character device */ + VXFS_IFDIR = 0x00004000, /* Directory */ + VXFS_IFNAM = 0x00005000, /* Xenix device ?? */ + VXFS_IFBLK = 0x00006000, /* Block device */ + VXFS_IFREG = 0x00008000, /* Regular file */ + VXFS_IFCMP = 0x00009000, /* Compressed file ?!? */ + VXFS_IFLNK = 0x0000a000, /* Symlink */ + VXFS_IFSOC = 0x0000c000, /* Socket */ + + /* VxFS internal */ + VXFS_IFFSH = 0x10000000, /* Fileset header */ + VXFS_IFILT = 0x20000000, /* Inode list */ + VXFS_IFIAU = 0x30000000, /* Inode allocation unit */ + VXFS_IFCUT = 0x40000000, /* Current usage table */ + VXFS_IFATT = 0x50000000, /* Attr. inode */ + VXFS_IFLCT = 0x60000000, /* Link count table */ + VXFS_IFIAT = 0x70000000, /* Indirect attribute file */ + VXFS_IFEMR = 0x80000000, /* Extent map reorg file */ + VXFS_IFQUO = 0x90000000, /* BSD quota file */ + VXFS_IFPTI = 0xa0000000, /* "Pass through" inode */ + VXFS_IFLAB = 0x11000000, /* Device label file */ + VXFS_IFOLT = 0x12000000, /* OLT file */ + VXFS_IFLOG = 0x13000000, /* Log file */ + VXFS_IFEMP = 0x14000000, /* Extent map file */ + VXFS_IFEAU = 0x15000000, /* Extent AU file */ + VXFS_IFAUS = 0x16000000, /* Extent AU summary file */ + VXFS_IFDEV = 0x17000000, /* Device config file */ + +}; + +#define VXFS_TYPE_MASK 0xfffff000 + +#define VXFS_IS_TYPE(ip,type) (((ip)->vii_mode & VXFS_TYPE_MASK) == (type)) +#define VXFS_ISFIFO(x) VXFS_IS_TYPE((x),VXFS_IFIFO) +#define VXFS_ISCHR(x) VXFS_IS_TYPE((x),VXFS_IFCHR) +#define VXFS_ISDIR(x) VXFS_IS_TYPE((x),VXFS_IFDIR) +#define VXFS_ISNAM(x) VXFS_IS_TYPE((x),VXFS_IFNAM) +#define VXFS_ISBLK(x) VXFS_IS_TYPE((x),VXFS_IFBLK) +#define VXFS_ISLNK(x) VXFS_IS_TYPE((x),VXFS_IFLNK) +#define VXFS_ISREG(x) VXFS_IS_TYPE((x),VXFS_IFREG) +#define VXFS_ISCMP(x) VXFS_IS_TYPE((x),VXFS_IFCMP) +#define VXFS_ISSOC(x) VXFS_IS_TYPE((x),VXFS_IFSOC) + +#define VXFS_ISFSH(x) VXFS_IS_TYPE((x),VXFS_IFFSH) +#define VXFS_ISILT(x) VXFS_IS_TYPE((x),VXFS_IFILT) + +/* + * Inmode organisation types. + */ +enum { + VXFS_ORG_NONE = 0, /* Inode has *no* format ?!? */ + VXFS_ORG_EXT4 = 1, /* Ext4 */ + VXFS_ORG_IMMED = 2, /* All data stored in inode */ + VXFS_ORG_TYPED = 3, /* Typed extents */ +}; + +#define VXFS_IS_ORG(ip,org) ((ip)->vii_orgtype == (org)) +#define VXFS_ISNONE(ip) VXFS_IS_ORG((ip), VXFS_ORG_NONE) +#define VXFS_ISEXT4(ip) VXFS_IS_ORG((ip), VXFS_ORG_EXT4) +#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)->u.generic_ip) + +/* + * Get filesystem private data from VFS superblock. + */ +#define VXFS_SBI(sbp) \ + ((struct vxfs_sb_info *)(sbp)->s_fs_info) + +#endif /* _VXFS_SUPER_H_ */ diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c new file mode 100644 index 00000000000..bc4b57da306 --- /dev/null +++ b/fs/freevxfs/vxfs_bmap.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2000-2001 Christoph Hellwig. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Veritas filesystem driver - filesystem to disk block mapping. + */ +#include <linux/fs.h> +#include <linux/buffer_head.h> +#include <linux/kernel.h> + +#include "vxfs.h" +#include "vxfs_inode.h" + + +#ifdef DIAGNOSTIC +static void +vxfs_typdump(struct vxfs_typed *typ) +{ + printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT); + printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + printk("block=%x ", typ->vt_block); + printk("size=%x\n", typ->vt_size); +} +#endif + +/** + * vxfs_bmap_ext4 - do bmap for ext4 extents + * @ip: pointer to the inode we do bmap for + * @iblock: logical block. + * + * Description: + * vxfs_bmap_ext4 performs the bmap operation for inodes with + * ext4-style extents (which are much like the traditional UNIX + * inode organisation). + * + * Returns: + * The physical block number on success, else Zero. + */ +static daddr_t +vxfs_bmap_ext4(struct inode *ip, long bn) +{ + struct super_block *sb = ip->i_sb; + struct vxfs_inode_info *vip = VXFS_INO(ip); + unsigned long bsize = sb->s_blocksize; + u32 indsize = vip->vii_ext4.ve4_indsize; + int i; + + if (indsize > sb->s_blocksize) + goto fail_size; + + 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 / (indsize * indsize * bsize / 4)) == 0) { + struct buffer_head *buf; + daddr_t bno; + u32 *indir; + + buf = sb_bread(sb, 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); + + brelse(buf); + return bno; + } else + printk(KERN_WARNING "no matching indir?"); + + return 0; + +fail_size: + printk("vxfs: indirect extent to big!\n"); +fail_buf: + return 0; +} + +/** + * vxfs_bmap_indir - recursion for vxfs_bmap_typed + * @ip: pointer to the inode we do bmap for + * @indir: indirect block we start reading at + * @size: size of the typed area to search + * @block: partially result from further searches + * + * Description: + * vxfs_bmap_indir reads a &struct vxfs_typed at @indir + * and performs the type-defined action. + * + * Return Value: + * The physical block number on success, else Zero. + * + * Note: + * Kernelstack is rare. Unrecurse? + */ +static daddr_t +vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) +{ + struct buffer_head *bp = NULL; + daddr_t pblock = 0; + int i; + + for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) { + struct vxfs_typed *typ; + int64_t off; + + bp = sb_bread(ip->i_sb, + indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb))); + if (!buffer_mapped(bp)) + return 0; + + typ = ((struct vxfs_typed *)bp->b_data) + + (i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); + off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + + if (block < off) { + brelse(bp); + continue; + } + + switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { + case VXFS_TYPED_INDIRECT: + pblock = vxfs_bmap_indir(ip, typ->vt_block, + typ->vt_size, block - off); + if (pblock == -2) + break; + goto out; + case VXFS_TYPED_DATA: + if ((block - off) >= typ->vt_size) + break; + pblock = (typ->vt_block + block - off); + goto out; + case VXFS_TYPED_INDIRECT_DEV4: + case VXFS_TYPED_DATA_DEV4: { + struct vxfs_typed_dev4 *typ4 = + (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); + goto fail; + } + default: + BUG(); + } + brelse(bp); + } + +fail: + pblock = 0; +out: + brelse(bp); + return (pblock); +} + +/** + * vxfs_bmap_typed - bmap for typed extents + * @ip: pointer to the inode we do bmap for + * @iblock: logical block + * + * Description: + * Performs the bmap operation for typed extents. + * + * Return Value: + * The physical block number on success, else Zero. + */ +static daddr_t +vxfs_bmap_typed(struct inode *ip, long iblock) +{ + struct vxfs_inode_info *vip = VXFS_INO(ip); + 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); + +#ifdef DIAGNOSTIC + vxfs_typdump(typ); +#endif + if (iblock < off) + continue; + switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { + case VXFS_TYPED_INDIRECT: + pblock = vxfs_bmap_indir(ip, typ->vt_block, + 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); + break; + case VXFS_TYPED_INDIRECT_DEV4: + case VXFS_TYPED_DATA_DEV4: { + struct vxfs_typed_dev4 *typ4 = + (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); + return 0; + } + default: + BUG(); + } + } + + return 0; +} + +/** + * vxfs_bmap1 - vxfs-internal bmap operation + * @ip: pointer to the inode we do bmap for + * @iblock: logical block + * + * Description: + * vxfs_bmap1 perfoms a logical to physical block mapping + * for vxfs-internal purposes. + * + * Return Value: + * The physical block number on success, else Zero. + */ +daddr_t +vxfs_bmap1(struct inode *ip, long iblock) +{ + struct vxfs_inode_info *vip = VXFS_INO(ip); + + if (VXFS_ISEXT4(vip)) + return vxfs_bmap_ext4(ip, iblock); + if (VXFS_ISTYPED(vip)) + return vxfs_bmap_typed(ip, iblock); + if (VXFS_ISNONE(vip)) + goto unsupp; + if (VXFS_ISIMMED(vip)) + goto unsupp; + + printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n", + ip->i_ino, vip->vii_orgtype); + BUG(); + +unsupp: + printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n", + ip->i_ino, vip->vii_orgtype); + return 0; +} diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h new file mode 100644 index 00000000000..8a4dfef1dda --- /dev/null +++ b/fs/freevxfs/vxfs_dir.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2000-2001 Christoph Hellwig. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _VXFS_DIR_H_ +#define _VXFS_DIR_H_ + +/* + * Veritas filesystem driver - directory structure. + * + * This file contains the definition of the vxfs directory format. + */ + + +/* + * VxFS directory block header. + * + * This entry is the head of every filesystem block in a directory. + * It is used for free space managment and additionally includes + * a hash for speeding up directory search (lookup). + * + * The hash may be empty and in fact we do not use it all in the + * 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 */ +}; + +/* + * VXFS_NAMELEN is the maximum length of the d_name field + * of an VxFS directory entry. + */ +#define VXFS_NAMELEN 256 + +/* + * 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 */ + char d_name[VXFS_NAMELEN]; /* name */ +}; + +/* + * VXFS_DIRPAD defines the directory entry boundaries, is _must_ be + * a multiple of four. + * VXFS_NAMEMIN is the length of a directory entry with a NULL d_name. + * VXFS_DIRROUND is an internal macros that rounds a length to a value + * usable for directory sizes. + * VXFS_DIRLEN calculates the directory entry size for an entry with + * a d_name with size len. + */ +#define VXFS_DIRPAD 4 +#define VXFS_NAMEMIN ((int)((struct vxfs_direct *)0)->d_name) +#define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1)) +#define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len))) + +/* + * VXFS_DIRBLKOV is the overhead of a specific dirblock. + */ +#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4) + +#endif /* _VXFS_DIR_H_ */ diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h new file mode 100644 index 00000000000..d8be917f979 --- /dev/null +++ b/fs/freevxfs/vxfs_extern.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000-2001 Christoph Hellwig. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef _VXFS_EXTERN_H_ +#define _VXFS_EXTERN_H_ + +/* + * Veritas filesystem driver - external prototypes. + * + * This file contains prototypes for all vxfs functions used + * outside their respective source files. + */ + + +struct kmem_cache_s; +struct super_block; +struct vxfs_inode_info; +struct inode; + + +/* vxfs_bmap.c */ +extern daddr_t vxfs_bmap1(struct inode *, long); + +/* vxfs_fshead.c */ +extern int vxfs_read_fshead(struct super_block *); + +/* vxfs_inode.c */ +extern struct kmem_cache_s *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 void vxfs_read_inode(struct inode *); +extern void vxfs_clear_inode(struct inode *); + +/* vxfs_lookup.c */ +extern struct inode_operations vxfs_dir_inode_ops; +extern struct file_operations vxfs_dir_operations; + +/* vxfs_olt.c */ +extern int vxfs_read_olt(struct super_block *, u_long); + +/* vxfs_subr.c */ +extern struct page * vxfs_get_page(struct address_space *, u_long); +extern void vxfs_put_page(struct page *); +extern struct buffer_head * vxfs_bread(struct inode *, int); + +#endif /* _VXFS_EXTERN_H_ */ diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c new file mode 100644 index 00000000000..05b19f70bf9 --- /dev/null +++ b/fs/freevxfs/vxfs_fshead.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2000-2001 Christoph Hellwig. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Veritas filesystem driver - fileset header routines. + */ +#include <linux/fs.h> +#include <linux/buffer_head.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include "vxfs.h" +#include "vxfs_inode.h" +#include "vxfs_extern.h" +#include "vxfs_fshead.h" + + +#ifdef DIAGNOSTIC +static void +vxfs_dumpfsh(struct vxfs_fsh *fhp) +{ + printk("\n\ndumping fileset header:\n"); + printk("----------------------------\n"); + printk("version: %u\n", fhp->fsh_version); + printk("fsindex: %u\n", fhp->fsh_fsindex); + printk("iauino: %u\tninodes:%u\n", + fhp->fsh_iauino, fhp->fsh_ninodes); + printk("maxinode: %u\tlctino: %u\n", + fhp->fsh_maxinode, fhp->fsh_lctino); + printk("nau: %u\n", fhp->fsh_nau); + printk("ilistino[0]: %u\tilistino[1]: %u\n", + fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]); +} +#endif + +/** + * vxfs_getfsh - read fileset header into memory + * @ip: the (fake) fileset header inode + * @which: 0 for the structural, 1 for the primary fsh. + * + * Description: + * vxfs_getfsh reads either the structural or primary fileset header + * described by @ip into memory. + * + * Returns: + * The fileset header structure on success, else Zero. + */ +static struct vxfs_fsh * +vxfs_getfsh(struct inode *ip, int which) +{ + struct buffer_head *bp; + + bp = vxfs_bread(ip, which); + if (buffer_mapped(bp)) { + struct vxfs_fsh *fhp; + + if (!(fhp = kmalloc(sizeof(*fhp), SLAB_KERNEL))) + return NULL; + memcpy(fhp, bp->b_data, sizeof(*fhp)); + + brelse(bp); + return (fhp); + } + + return NULL; +} + +/** + * vxfs_read_fshead - read the fileset headers + * @sbp: superblock to which the fileset belongs + * + * Description: + * vxfs_read_fshead will fill the inode and structural inode list in @sb. + * + * Returns: + * Zero on success, else a negative error code (-EINVAL). + */ +int +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; + + vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); + if (!vip) { + printk(KERN_ERR "vxfs: unabled to read fsh inode\n"); + return -EINVAL; + } + 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; + } + + +#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: unabled to get fsh inode\n"); + goto out_free_fship; + } + + sfp = vxfs_getfsh(infp->vsi_fship, 0); + if (!sfp) { + printk(KERN_ERR "vxfs: unabled to get structural fsh\n"); + goto out_iput_fship; + } + +#ifdef DIAGNOSTIC + vxfs_dumpfsh(sfp); +#endif + + pfp = vxfs_getfsh(infp->vsi_fship, 1); + if (!pfp) { + printk(KERN_ERR "vxfs: unabled to get primary fsh\n"); + goto out_free_sfp; + } + +#ifdef DIAGNOSTIC + 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); + if (!infp->vsi_stilist) { + printk(KERN_ERR "vxfs: unabled to get structual list inode\n"); + kfree(tip); + goto out_free_pfp; + } + if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { + printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", + VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); + 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); + if (!infp->vsi_ilist) { + printk(KERN_ERR "vxfs: unabled to get inode list inode\n"); + kfree(tip); + goto out_iput_stilist; + } + if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { + printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", + VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); + goto out_iput_ilist; + } + + return 0; + + out_iput_ilist: + iput(infp->vsi_ilist); + out_iput_stilist: + iput(infp->vsi_stilist); + out_free_pfp: + kfree(pfp); + out_free_sfp: + kfree(sfp); + 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 new file mode 100644 index 00000000000..ead0d640c18 --- /dev/null +++ b/fs/freevxfs/vxfs_fshead.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000-2001 Christoph Hellwig. + * All rights reserved. |