Linux-2.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!
This commit is contained in:
Linus Torvalds 2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

8
fs/freevxfs/Makefile Normal file
View file

@ -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

264
fs/freevxfs/vxfs.h Normal file
View file

@ -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_ */

280
fs/freevxfs/vxfs_bmap.c Normal file
View file

@ -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;
}

92
fs/freevxfs/vxfs_dir.h Normal file
View file

@ -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_ */

76
fs/freevxfs/vxfs_extern.h Normal file
View file

@ -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_ */

202
fs/freevxfs/vxfs_fshead.c Normal file
View file

@ -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;
}

67
fs/freevxfs/vxfs_fshead.h Normal file
View file

@ -0,0 +1,67 @@
/*
* 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_FSHEAD_H_
#define _VXFS_FSHEAD_H_
/*
* Veritas filesystem driver - fileset header structures.
*
* This file contains the physical structure of the VxFS
* fileset header.
*/
/*
* Fileset header
*/
struct vxfs_fsh {
u_int32_t fsh_version; /* fileset header version */
u_int32_t fsh_fsindex; /* fileset index */
u_int32_t fsh_time; /* modification time - sec */
u_int32_t fsh_utime; /* modification time - usec */
u_int32_t fsh_extop; /* extop flags */
vx_ino_t fsh_ninodes; /* allocated inodes */
u_int32_t fsh_nau; /* number of IAUs */
u_int32_t fsh_old_ilesize; /* old size of ilist */
u_int32_t fsh_dflags; /* flags */
u_int32_t fsh_quota; /* quota limit */
vx_ino_t fsh_maxinode; /* maximum inode number */
vx_ino_t fsh_iauino; /* IAU inode */
vx_ino_t fsh_ilistino[2]; /* ilist inodes */
vx_ino_t fsh_lctino; /* link count table inode */
/*
* Slightly more fields follow, but they
* a) are not of any interest for us, and
* b) differ a lot in different vxfs versions/ports
*/
};
#endif /* _VXFS_FSHEAD_H_ */

114
fs/freevxfs/vxfs_immed.c Normal file
View file

@ -0,0 +1,114 @@
/*
* 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 - support for 'immed' inodes.
*/
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/namei.h>
#include "vxfs.h"
#include "vxfs_inode.h"
static int vxfs_immed_follow_link(struct dentry *, struct nameidata *);
static int vxfs_immed_readpage(struct file *, struct page *);
/*
* Inode operations for immed symlinks.
*
* Unliked all other operations we do not go through the pagecache,
* but do all work directly on the inode.
*/
struct inode_operations vxfs_immed_symlink_iops = {
.readlink = generic_readlink,
.follow_link = vxfs_immed_follow_link,
};
/*
* Adress space operations for immed files and directories.
*/
struct address_space_operations vxfs_immed_aops = {
.readpage = vxfs_immed_readpage,
};
/**
* vxfs_immed_follow_link - follow immed symlink
* @dp: dentry for the link
* @np: pathname lookup data for the current path walk
*
* Description:
* vxfs_immed_follow_link restarts the pathname lookup with
* the data obtained from @dp.
*
* Returns:
* Zero on success, else a negative error code.
*/
static int
vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
{
struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode);
nd_set_link(np, vip->vii_immed.vi_immed);
return 0;
}
/**
* vxfs_immed_readpage - read part of an immed inode into pagecache
* @file: file context (unused)
* @page: page frame to fill in.
*
* Description:
* vxfs_immed_readpage reads a part of the immed area of the
* file that hosts @pp into the pagecache.
*
* Returns:
* Zero on success, else a negative error code.
*
* Locking status:
* @page is locked and will be unlocked.
*/
static int
vxfs_immed_readpage(struct file *fp, struct page *pp)
{
struct vxfs_inode_info *vip = VXFS_INO(pp->mapping->host);
u_int64_t offset = pp->index << PAGE_CACHE_SHIFT;
caddr_t kaddr;
kaddr = kmap(pp);
memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE);
kunmap(pp);
flush_dcache_page(pp);
SetPageUptodate(pp);
unlock_page(pp);
return 0;
}

351
fs/freevxfs/vxfs_inode.c Normal file
View file

@ -0,0 +1,351 @@
/*
* 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 - inode routines.
*/
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/pagemap.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "vxfs.h"
#include "vxfs_inode.h"
#include "vxfs_extern.h"
extern struct address_space_operations vxfs_aops;
extern struct address_space_operations vxfs_immed_aops;
extern struct inode_operations vxfs_immed_symlink_iops;
static struct file_operations vxfs_file_operations = {
.open = generic_file_open,
.llseek = generic_file_llseek,
.read = generic_file_read,
.mmap = generic_file_mmap,
.sendfile = generic_file_sendfile,
};
kmem_cache_t *vxfs_inode_cachep;
#ifdef DIAGNOSTIC
/*
* Dump inode contents (partially).
*/
void
vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
{
printk(KERN_DEBUG "\n\n");
if (ino)
printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino);
else
printk(KERN_DEBUG "dumping unknown vxfs inode\n");
printk(KERN_DEBUG "---------------------------\n");
printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
vip->vii_nlink, vip->vii_uid, vip->vii_gid);
printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
vip->vii_size, vip->vii_blocks);
printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
}
#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 (buffer_mapped(bp)) {
struct vxfs_inode_info *vip;
struct vxfs_dinode *dip;
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_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 a NULL pointer.
*/
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, SLAB_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 NULL;
fail:
printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
vxfs_put_page(pp);
return NULL;
}
/**
* 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)
{
return __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
}
/**
* vxfs_transmod - mode for a VxFS inode
* @vip: VxFS inode
*
* Description:
* vxfs_transmod returns a Linux mode_t for a given
* VxFS inode structure.
*/
static __inline__ mode_t
vxfs_transmod(struct vxfs_inode_info *vip)
{
mode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
if (VXFS_ISFIFO(vip))
ret |= S_IFIFO;
if (VXFS_ISCHR(vip))
ret |= S_IFCHR;
if (VXFS_ISDIR(vip))
ret |= S_IFDIR;
if (VXFS_ISBLK(vip))
ret |= S_IFBLK;
if (VXFS_ISLNK(vip))
ret |= S_IFLNK;
if (VXFS_ISREG(vip))
ret |= S_IFREG;
if (VXFS_ISSOC(vip))
ret |= S_IFSOCK;
return (ret);
}
/**
* vxfs_iinit- helper to fill inode fields
* @ip: VFS inode
* @vip: VxFS inode
*
* Description:
* vxfs_instino is a helper function to fill in all relevant
* fields in @ip from @vip.
*/
static void
vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
{
ip->i_mode = vxfs_transmod(vip);
ip->i_uid = (uid_t)vip->vii_uid;
ip->i_gid = (gid_t)vip->vii_gid;
ip->i_nlink = vip->vii_nlink;
ip->i_size = vip->vii_size;
ip->i_atime.tv_sec = vip->vii_atime;
ip->i_ctime.tv_sec = vip->vii_ctime;
ip->i_mtime.tv_sec = vip->vii_mtime;
ip->i_atime.tv_nsec = 0;
ip->i_ctime.tv_nsec = 0;
ip->i_mtime.tv_nsec = 0;
ip->i_blksize = PAGE_SIZE;
ip->i_blocks = vip->vii_blocks;
ip->i_generation = vip->vii_gen;
ip->u.generic_ip = (void *)vip;
}
/**
* vxfs_get_fake_inode - get fake inode structure
* @sbp: filesystem superblock
* @vip: fspriv inode
*
* Description:
* vxfs_fake_inode gets a fake inode (not in the inode hash) for a
* superblock, vxfs_inode pair.
* Returns the filled VFS inode.
*/
struct inode *
vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
{
struct inode *ip = NULL;
if ((ip = new_inode(sbp))) {
vxfs_iinit(ip, vip);
ip->i_mapping->a_ops = &vxfs_aops;
}
return (ip);
}
/**
* vxfs_put_fake_inode - free faked inode
* *ip: VFS inode
*
* Description:
* vxfs_put_fake_inode frees all data asssociated with @ip.
*/
void
vxfs_put_fake_inode(struct inode *ip)
{
iput(ip);
}
/**
* vxfs_read_inode - fill in inode information
* @ip: inode pointer to fill
*
* Description:
* vxfs_read_inode reads the disk inode for @ip and fills
* in all relevant fields in @ip.
*/
void
vxfs_read_inode(struct inode *ip)
{
struct super_block *sbp = ip->i_sb;
struct vxfs_inode_info *vip;
struct address_space_operations *aops;
ino_t ino = ip->i_ino;
if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist)))
return;
vxfs_iinit(ip, vip);
if (VXFS_ISIMMED(vip))
aops = &vxfs_immed_aops;
else
aops = &vxfs_aops;
if (S_ISREG(ip->i_mode)) {
ip->i_fop = &vxfs_file_operations;
ip->i_mapping->a_ops = aops;
} else if (S_ISDIR(ip->i_mode)) {
ip->i_op = &vxfs_dir_inode_ops;
ip->i_fop = &vxfs_dir_operations;
ip->i_mapping->a_ops = aops;
} else if (S_ISLNK(ip->i_mode)) {
if (!VXFS_ISIMMED(vip)) {
ip->i_op = &page_symlink_inode_operations;
ip->i_mapping->a_ops = &vxfs_aops;
} else
ip->i_op = &vxfs_immed_symlink_iops;
} else
init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev));
return;
}
/**
* vxfs_clear_inode - remove inode from main memory
* @ip: inode to discard.
*
* Description:
* vxfs_clear_inode() is called on the final iput and frees the private
* inode area.
*/
void
vxfs_clear_inode(struct inode *ip)
{
kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
}

180
fs/freevxfs/vxfs_inode.h Normal file
View file

@ -0,0 +1,180 @@
/*
* 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_INODE_H_
#define _VXFS_INODE_H_
/*
* Veritas filesystem driver - inode structure.
*
* This file contains the definition of the disk and core
* inodes of the Veritas Filesystem.
*/
#define VXFS_ISIZE 0x100 /* Inode size */
#define VXFS_NDADDR 10 /* Number of direct addrs in inode */
#define VXFS_NIADDR 2 /* Number of indirect addrs in inode */
#define VXFS_NIMMED 96 /* Size of immediate data in inode */
#define VXFS_NTYPED 6 /* Num of typed extents */
#define VXFS_TYPED_OFFSETMASK (0x00FFFFFFFFFFFFFFULL)
#define VXFS_TYPED_TYPEMASK (0xFF00000000000000ULL)
#define VXFS_TYPED_TYPESHIFT 56
#define VXFS_TYPED_PER_BLOCK(sbp) \
((sbp)->s_blocksize / sizeof(struct vxfs_typed))
/*
* Possible extent descriptor types for %VXFS_ORG_TYPED extents.
*/
enum {
VXFS_TYPED_INDIRECT = 1,
VXFS_TYPED_DATA = 2,
VXFS_TYPED_INDIRECT_DEV4 = 3,
VXFS_TYPED_DATA_DEV4 = 4,
};
/*
* Data stored immediately in the inode.
*/
struct vxfs_immed {
u_int8_t vi_immed[VXFS_NIMMED];
};
struct vxfs_ext4 {
u_int32_t ve4_spare; /* ?? */
u_int32_t ve4_indsize; /* Indirect extent size */
vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */
struct direct { /* Direct extents */
vx_daddr_t extent; /* Extent number */
int32_t size; /* Size of extent */
} ve4_direct[VXFS_NDADDR];
};
struct vxfs_typed {
u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
vx_daddr_t vt_block; /* Extent block */
int32_t vt_size; /* Size in blocks */
};
struct vxfs_typed_dev4 {
u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
u_int64_t vd4_block; /* Extent block */
u_int64_t vd4_size; /* Size in blocks */
int32_t vd4_dev; /* Device ID */
u_int32_t __pad1;
};
/*
* The inode as contained on the physical device.
*/
struct vxfs_dinode {
int32_t vdi_mode;
u_int32_t vdi_nlink; /* Link count */
u_int32_t vdi_uid; /* UID */
u_int32_t vdi_gid; /* GID */
u_int64_t vdi_size; /* Inode size in bytes */
u_int32_t vdi_atime; /* Last time accessed - sec */
u_int32_t vdi_autime; /* Last time accessed - usec */
u_int32_t vdi_mtime; /* Last modify time - sec */
u_int32_t vdi_mutime; /* Last modify time - usec */
u_int32_t vdi_ctime; /* Create time - sec */
u_int32_t vdi_cutime; /* Create time - usec */
u_int8_t vdi_aflags; /* Allocation flags */
u_int8_t vdi_orgtype; /* Organisation type */
u_int16_t vdi_eopflags;
u_int32_t vdi_eopdata;
union {
u_int32_t rdev;
u_int32_t dotdot;
struct {
u_int32_t reserved;
u_int32_t fixextsize;
} i_regular;
struct {
u_int32_t matchino;
u_int32_t fsetindex;
} i_vxspec;
u_int64_t align;
} vdi_ftarea;
u_int32_t vdi_blocks; /* How much blocks does inode occupy */
u_int32_t vdi_gen; /* Inode generation */
u_int64_t vdi_version; /* Version */
union {
struct vxfs_immed immed;
struct vxfs_ext4 ext4;
struct vxfs_typed typed[VXFS_NTYPED];
} vdi_org;
u_int32_t vdi_iattrino;
};
#define vdi_rdev vdi_ftarea.rdev
#define vdi_dotdot vdi_ftarea.dotdot
#define vdi_fixextsize vdi_ftarea.regular.fixextsize
#define vdi_matchino vdi_ftarea.vxspec.matchino
#define vdi_fsetindex vdi_ftarea.vxspec.fsetindex
#define vdi_immed vdi_org.immed
#define vdi_ext4 vdi_org.ext4
#define vdi_typed vdi_org.typed
/*
* The inode as represented in the main memory.
*
* TBD: This should become a separate structure...
*/
#define vxfs_inode_info vxfs_dinode
#define vii_mode vdi_mode
#define vii_uid vdi_uid
#define vii_gid vdi_gid
#define vii_nlink vdi_nlink
#define vii_size vdi_size
#define vii_atime vdi_atime
#define vii_ctime vdi_ctime
#define vii_mtime vdi_mtime
#define vii_blocks vdi_blocks
#define vii_org vdi_org
#define vii_orgtype vdi_orgtype
#define vii_gen vdi_gen
#define vii_rdev vdi_ftarea.rdev
#define vii_dotdot vdi_ftarea.dotdot
#define vii_fixextsize vdi_ftarea.regular.fixextsize
#define vii_matchino vdi_ftarea.vxspec.matchino
#define vii_fsetindex vdi_ftarea.vxspec.fsetindex
#define vii_immed vdi_org.immed
#define vii_ext4 vdi_org.ext4
#define vii_typed vdi_org.typed
#endif /* _VXFS_INODE_H_ */

View file

@ -0,0 +1,49 @@
#ifndef _VXFS_KCOMPAT_H
#define _VXFS_KCOMPAT_H
#include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include <linux/blkdev.h>
typedef long sector_t;
/* From include/linux/fs.h (Linux 2.5.2-pre3) */
static inline struct buffer_head * sb_bread(struct super_block *sb, int block)
{
return bread(sb->s_dev, block, sb->s_blocksize);
}
/* Dito. */
static inline void map_bh(struct buffer_head *bh, struct super_block *sb, int block)
{
bh->b_state |= 1 << BH_Mapped;
bh->b_dev = sb->s_dev;
bh->b_blocknr = block;
}
/* From fs/block_dev.c (Linux 2.5.2-pre2) */
static inline int sb_set_blocksize(struct super_block *sb, int size)
{
int bits;
if (set_blocksize(sb->s_dev, size) < 0)
return 0;
sb->s_blocksize = size;
for (bits = 9, size >>= 9; size >>= 1; bits++)
;
sb->s_blocksize_bits = bits;
return sb->s_blocksize;
}
/* Dito. */
static inline int sb_min_blocksize(struct super_block *sb, int size)
{
int minsize = get_hardsect_size(sb->s_dev);
if (size < minsize)
size = minsize;
return sb_set_blocksize(sb, size);
}
#endif /* Kernel 2.4 */
#endif /* _VXFS_KCOMPAT_H */

328
fs/freevxfs/vxfs_lookup.c Normal file
View file

@ -0,0 +1,328 @@
/*
* 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 - lookup and other directory related code.
*/
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include "vxfs.h"
#include "vxfs_dir.h"
#include "vxfs_inode.h"
#include "vxfs_extern.h"
/*
* Number of VxFS blocks per page.
*/
#define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int vxfs_readdir(struct file *, void *, filldir_t);
struct inode_operations vxfs_dir_inode_ops = {
.lookup = vxfs_lookup,
};
struct file_operations vxfs_dir_operations = {
.readdir = vxfs_readdir,
};
static __inline__ u_long
dir_pages(struct inode *inode)
{
return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
}
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
* @ip: directory inode
* @dp: dentry for which we want to find a direct
* @ppp: gets filled with the page the return value sits in
*
* Description:
* vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
* cache entry @dp. @ppp will be filled with the page the return
* value resides in.
*
* Returns:
* The wanted direct on success, else a NULL pointer.
*/
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
u_long npages, page, nblocks, pblocks, block;
u_long bsize = ip->i_sb->s_blocksize;
const char *name = dp->d_name.name;
int namelen = dp->d_name.len;
npages = dir_pages(ip);
nblocks = dir_blocks(ip);
pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
for (page = 0; page < npages; page++) {
caddr_t kaddr;
struct page *pp;
pp = vxfs_get_page(ip->i_mapping, page);
if (IS_ERR(pp))
continue;
kaddr = (caddr_t)page_address(pp);
for (block = 0; block <= nblocks && block <= pblocks; block++) {
caddr_t baddr, limit;
struct vxfs_dirblk *dbp;
struct vxfs_direct *de;
baddr = kaddr + (block * bsize);
limit = baddr + bsize - VXFS_DIRLEN(1);
dbp = (struct vxfs_dirblk *)baddr;
de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
if (!de->d_reclen)
break;
if (!de->d_ino)
continue;
if (vxfs_match(namelen, name, de)) {
*ppp = pp;
return (de);
}
}
}
vxfs_put_page(pp);
}
return NULL;
}
/**
* vxfs_inode_by_name - find inode number for dentry
* @dip: directory to search in
* @dp: dentry we seach for
*
* Description:
* vxfs_inode_by_name finds out the inode number of
* the path component described by @dp in @dip.
*
* Returns:
* The wanted inode number on success, else Zero.
*/
static ino_t
vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
{
struct vxfs_direct *de;
struct page *pp;
ino_t ino = 0;
de = vxfs_find_entry(dip, dp, &pp);
if (de) {
ino = de->d_ino;
kunmap(pp);
page_cache_release(pp);
}
return (ino);
}
/**
* vxfs_lookup - lookup pathname component
* @dip: dir in which we lookup
* @dp: dentry we lookup
* @nd: lookup nameidata
*
* Description:
* vxfs_lookup tries to lookup the pathname component described
* by @dp in @dip.
*
* Returns:
* A NULL-pointer on success, else an negative error code encoded
* in the return pointer.
*/
static struct dentry *
vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
{
struct inode *ip = NULL;
ino_t ino;
if (dp->d_name.len > VXFS_NAMELEN)
return ERR_PTR(-ENAMETOOLONG);
lock_kernel();
ino = vxfs_inode_by_name(dip, dp);
if (ino) {
ip = iget(dip->i_sb, ino);
if (!ip) {
unlock_kernel();
return ERR_PTR(-EACCES);
}
}
unlock_kernel();
d_add(dp, ip);
return NULL;
}
/**
* vxfs_readdir - read a directory
* @fp: the directory to read
* @retp: return buffer
* @filler: filldir callback
*
* Description:
* vxfs_readdir fills @retp with directory entries from @fp
* using the VFS supplied callback @filler.
*
* Returns:
* Zero.
*/
static int
vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
{
struct inode *ip = fp->f_dentry->d_inode;
struct super_block *sbp = ip->i_sb;
u_long bsize = sbp->s_blocksize;
u_long page, npages, block, pblocks, nblocks, offset;
loff_t pos;
switch ((long)fp->f_pos) {
case 0:
if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
goto out;
fp->f_pos++;
/* fallthrough */
case 1:
if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0)
goto out;
fp->f_pos++;
/* fallthrough */
}
pos = fp->f_pos - 2;
if (pos > VXFS_DIRROUND(ip->i_size)) {
unlock_kernel();
return 0;
}
npages = dir_pages(ip);
nblocks = dir_blocks(ip);
pblocks = VXFS_BLOCK_PER_PAGE(sbp);
page = pos >> PAGE_CACHE_SHIFT;
offset = pos & ~PAGE_CACHE_MASK;
block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
for (; page < npages; page++, block = 0) {
caddr_t kaddr;
struct page *pp;
pp = vxfs_get_page(ip->i_mapping, page);
if (IS_ERR(pp))
continue;
kaddr = (caddr_t)page_address(pp);
for (; block <= nblocks && block <= pblocks; block++) {
caddr_t baddr, limit;
struct vxfs_dirblk *dbp;
struct vxfs_direct *de;
baddr = kaddr + (block * bsize);
limit = baddr + bsize - VXFS_DIRLEN(1);
dbp = (struct vxfs_dirblk *)baddr;
de = (struct vxfs_direct *)
(offset ?
(kaddr + offset) :
(baddr + VXFS_DIRBLKOV(dbp)));
for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
int over;
if (!de->d_reclen)
break;
if (!de->d_ino)
continue;
offset = (caddr_t)de - kaddr;
over = filler(retp, de->d_name, de->d_namelen,
((page << PAGE_CACHE_SHIFT) | offset) + 2,
de->d_ino, DT_UNKNOWN);
if (over) {
vxfs_put_page(pp);
goto done;
}
}
offset = 0;
}
vxfs_put_page(pp);
offset = 0;
}
done:
fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
out:
unlock_kernel();
return 0;
}

132
fs/freevxfs/vxfs_olt.c Normal file
View file

@ -0,0 +1,132 @@
/*
* 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 - object location table support.
*/
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
#include "vxfs.h"
#include "vxfs_olt.h"
static __inline__ void
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
{
if (infp->vsi_fshino)
BUG();
infp->vsi_fshino = fshp->olt_fsino[0];
}
static __inline__ void
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
{
if (infp->vsi_iext)
BUG();
infp->vsi_iext = ilistp->olt_iext[0];
}
static __inline__ u_long
vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
{
if (sbp->s_blocksize % bsize)
BUG();
return (block * (sbp->s_blocksize / bsize));
}
/**
* vxfs_read_olt - read olt
* @sbp: superblock of the filesystem
* @bsize: blocksize of the filesystem
*
* Description:
* vxfs_read_olt reads the olt of the filesystem described by @sbp
* into main memory and does some basic setup.
*
* Returns:
* Zero on success, else a negative error code.
*/
int
vxfs_read_olt(struct super_block *sbp, u_long bsize)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
struct buffer_head *bp;
struct vxfs_olt *op;
char *oaddr, *eaddr;
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
if (!bp || !bp->b_data)
goto fail;
op = (struct vxfs_olt *)bp->b_data;
if (op->olt_magic != VXFS_OLT_MAGIC) {
printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
goto fail;
}
/*
* It is in theory possible that vsi_oltsize is > 1.
* I've not seen any such filesystem yet and I'm lazy.. --hch
*/
if (infp->vsi_oltsize > 1) {
printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
printk(KERN_NOTICE "vxfs: please notify [email protected]\n");
goto fail;
}
oaddr = (char *)bp->b_data + op->olt_size;
eaddr = (char *)bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
while (oaddr < eaddr) {
struct vxfs_oltcommon *ocp =
(struct vxfs_oltcommon *)oaddr;
switch (ocp->olt_type) {
case VXFS_OLT_FSHEAD:
vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
break;
case VXFS_OLT_ILIST:
vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
break;
}
oaddr += ocp->olt_size;
}
brelse(bp);
return 0;
fail:
brelse(bp);
return -EINVAL;
}

145
fs/freevxfs/vxfs_olt.h Normal file
View file

@ -0,0 +1,145 @@
/*
* 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_OLT_H_
#define _VXFS_OLT_H_
/*
* Veritas filesystem driver - Object Location Table data structures.
*
* This file contains definitions for the Object Location Table used
* by the Veritas Filesystem version 2 and newer.
*/
/*
* OLT magic number (vxfs_olt->olt_magic).
*/
#define VXFS_OLT_MAGIC 0xa504FCF5
/*
* VxFS OLT entry types.
*/
enum {
VXFS_OLT_FREE = 1,
VXFS_OLT_FSHEAD = 2,
VXFS_OLT_CUT = 3,
VXFS_OLT_ILIST = 4,
VXFS_OLT_DEV = 5,
VXFS_OLT_SB = 6
};
/*
* VxFS OLT header.
*
* The Object Location Table header is placed at the beginning of each
* OLT extent. It is used to fing certain filesystem-wide metadata, e.g.
* the inital inode list, the fileset header or the device configuration.
*/
struct vxfs_olt {
u_int32_t olt_magic; /* magic number */
u_int32_t olt_size; /* size of this entry */
u_int32_t olt_checksum; /* checksum of extent */
u_int32_t __unused1; /* ??? */
u_int32_t olt_mtime; /* time of last mod. (sec) */
u_int32_t olt_mutime; /* time of last mod. (usec) */
u_int32_t olt_totfree; /* free space in OLT extent */
vx_daddr_t olt_extents[2]; /* addr of this extent, replica */
u_int32_t olt_esize; /* size of this extent */
vx_daddr_t olt_next[2]; /* addr of next extent, replica */
u_int32_t olt_nsize; /* size of next extent */
u_int32_t __unused2; /* align to 8 byte boundary */
};
/*
* VxFS common OLT entry (on disk).
*/
struct vxfs_oltcommon {
u_int32_t olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */
};
/*
* VxFS free OLT entry (on disk).
*/
struct vxfs_oltfree {
u_int32_t olt_type; /* type of this record */
u_int32_t olt_fsize; /* size of this free record */
};
/*
* VxFS initial-inode list (on disk).
*/
struct vxfs_oltilist {
u_int32_t olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */
vx_ino_t olt_iext[2]; /* initial inode list, replica */
};
/*
* Current Usage Table
*/
struct vxfs_oltcut {
u_int32_t olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */
vx_ino_t olt_cutino; /* inode of current usage table */
u_int32_t __pad; /* unused, 8 byte align */
};
/*
* Inodes containing Superblock, Intent log and OLTs
*/
struct vxfs_oltsb {
u_int32_t olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */
vx_ino_t olt_sbino; /* inode of superblock file */
u_int32_t __unused1; /* ??? */
vx_ino_t olt_logino[2]; /* inode of log file,replica */
vx_ino_t olt_oltino[2]; /* inode of OLT, replica */
};
/*
* Inode containing device configuration + it's replica
*/
struct vxfs_oltdev {
u_int32_t olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */
vx_ino_t olt_devino[2]; /* inode of device config files */
};
/*
* Fileset header
*/
struct vxfs_oltfshead {
u_int32_t olt_type; /* type number */
u_int32_t olt_size; /* size of this record */
vx_ino_t olt_fsino[2]; /* inodes of fileset header */
};
#endif /* _VXFS_OLT_H_ */

190
fs/freevxfs/vxfs_subr.c Normal file
View file

@ -0,0 +1,190 @@
/*
* 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 - shared subroutines.
*/
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include "vxfs_kcompat.h"
#include "vxfs_extern.h"
static int vxfs_readpage(struct file *, struct page *);
static sector_t vxfs_bmap(struct address_space *, sector_t);
struct address_space_operations vxfs_aops = {
.readpage = vxfs_readpage,
.bmap = vxfs_bmap,
.sync_page = block_sync_page,
};
inline void
vxfs_put_page(struct page *pp)
{
kunmap(pp);
page_cache_release(pp);
}
/**
* vxfs_get_page - read a page into memory.
* @ip: inode to read from
* @n: page number
*
* Description:
* vxfs_get_page reads the @n th page of @ip into the pagecache.
*
* Returns:
* The wanted page on success, else a NULL pointer.
*/
struct page *
vxfs_get_page(struct address_space *mapping, u_long n)
{
struct page * pp;
pp = read_cache_page(mapping, n,
(filler_t*)mapping->a_ops->readpage, NULL);
if (!IS_ERR(pp)) {
wait_on_page_locked(pp);
kmap(pp);
if (!PageUptodate(pp))
goto fail;
/** if (!PageChecked(pp)) **/
/** vxfs_check_page(pp); **/
if (PageError(pp))
goto fail;
}
return (pp);
fail:
vxfs_put_page(pp);
return ERR_PTR(-EIO);
}
/**
* vxfs_bread - read buffer for a give inode,block tuple
* @ip: inode
* @block: logical block
*
* Description:
* The vxfs_bread function reads block no @block of
* @ip into the buffercache.
*
* Returns:
* The resulting &struct buffer_head.
*/
struct buffer_head *
vxfs_bread(struct inode *ip, int block)
{
struct buffer_head *bp;
daddr_t pblock;
pblock = vxfs_bmap1(ip, block);
bp = sb_bread(ip->i_sb, pblock);
return (bp);
}
/**
* vxfs_get_block - locate buffer for given inode,block tuple
* @ip: inode
* @iblock: logical block
* @bp: buffer skeleton
* @create: %TRUE if blocks may be newly allocated.
*
* Description:
* The vxfs_get_block function fills @bp with the right physical
* block and device number to perform a lowlevel read/write on
* it.
*
* Returns:
* Zero on success, else a negativ error code (-EIO).
*/
static int
vxfs_getblk(struct inode *ip, sector_t iblock,
struct buffer_head *bp, int create)
{
daddr_t pblock;
pblock = vxfs_bmap1(ip, iblock);
if (pblock != 0) {
map_bh(bp, ip->i_sb, pblock);
return 0;
}
return -EIO;
}
/**
* vxfs_readpage - read one page synchronously into the pagecache
* @file: file context (unused)
* @page: page frame to fill in.
*
* Description:
* The vxfs_readpage routine reads @page synchronously into the
* pagecache.
*
* Returns:
* Zero on success, else a negative error code.
*
* Locking status:
* @page is locked and will be unlocked.
*/
static int
vxfs_readpage(struct file *file, struct page *page)
{
return block_read_full_page(page, vxfs_getblk);
}
/**
* vxfs_bmap - perform logical to physical block mapping
* @mapping: logical to physical mapping to use
* @block: logical block (relative to @mapping).
*
* Description:
* Vxfs_bmap find out the corresponding phsical block to the
* @mapping, @block pair.
*
* Returns:
* Physical block number on success, else Zero.
*
* Locking status:
* We are under the bkl.
*/
static sector_t
vxfs_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping, block, vxfs_getblk);
}

278
fs/freevxfs/vxfs_super.c Normal file
View file

@ -0,0 +1,278 @@
/*
* 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 - superblock related routines.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/vfs.h>
#include "vxfs.h"
#include "vxfs_extern.h"
#include "vxfs_dir.h"
#include "vxfs_inode.h"
MODULE_AUTHOR("Christoph Hellwig");
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */
static void vxfs_put_super(struct super_block *);
static int vxfs_statfs(struct super_block *, struct kstatfs *);
static int vxfs_remount(struct super_block *, int *, char *);
static struct super_operations vxfs_super_ops = {
.read_inode = vxfs_read_inode,
.clear_inode = vxfs_clear_inode,
.put_super = vxfs_put_super,
.statfs = vxfs_statfs,
.remount_fs = vxfs_remount,
};
/**
* vxfs_put_super - free superblock resources
* @sbp: VFS superblock.
*
* Description:
* vxfs_put_super frees all resources allocated for @sbp
* after the last instance of the filesystem is unmounted.
*/
static void
vxfs_put_super(struct super_block *sbp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
vxfs_put_fake_inode(infp->vsi_fship);
vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist);
brelse(infp->vsi_bp);
kfree(infp);
}
/**
* vxfs_statfs - get filesystem information
* @sbp: VFS superblock
* @bufp: output buffer
*
* Description:
* vxfs_statfs fills the statfs buffer @bufp with information
* about the filesystem described by @sbp.
*
* Returns:
* Zero.
*
* Locking:
* No locks held.
*
* Notes:
* This is everything but complete...
*/
static int
vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
bufp->f_type = VXFS_SUPER_MAGIC;
bufp->f_bsize = sbp->s_blocksize;
bufp->f_blocks = infp->vsi_raw->vs_dsize;
bufp->f_bfree = infp->vsi_raw->vs_free;
bufp->f_bavail = 0;
bufp->f_files = 0;
bufp->f_ffree = infp->vsi_raw->vs_ifree;
bufp->f_namelen = VXFS_NAMELEN;
return 0;
}
static int vxfs_remount(struct super_block *sb, int *flags, char *data)
{
*flags |= MS_RDONLY;
return 0;
}
/**
* vxfs_read_super - read superblock into memory and initalize filesystem
* @sbp: VFS superblock (to fill)
* @dp: fs private mount data
* @silent: do not complain loudly when sth is wrong
*
* Description:
* We are called on the first mount of a filesystem to read the
* superblock into memory and do some basic setup.
*
* Returns:
* The superblock on success, else %NULL.
*
* Locking:
* We are under the bkl and @sbp->s_lock.
*/
static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
{
struct vxfs_sb_info *infp;
struct vxfs_sb *rsbp;
struct buffer_head *bp = NULL;
u_long bsize;
struct inode *root;
sbp->s_flags |= MS_RDONLY;
infp = kmalloc(sizeof(*infp), GFP_KERNEL);
if (!infp) {
printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
return -ENOMEM;
}
memset(infp, 0, sizeof(*infp));
bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
if (!bsize) {
printk(KERN_WARNING "vxfs: unable to set blocksize\n");
goto out;
}
bp = sb_bread(sbp, 1);
if (!bp || !buffer_mapped(bp)) {
if (!silent) {
printk(KERN_WARNING
"vxfs: unable to read disk superblock\n");
}
goto out;
}
rsbp = (struct vxfs_sb *)bp->b_data;
if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
if (!silent)
printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
goto out;
}
if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
rsbp->vs_version);
goto out;
}
#ifdef DIAGNOSTIC
printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
#endif
sbp->s_magic = rsbp->vs_magic;
sbp->s_fs_info = (void *)infp;
infp->vsi_raw = rsbp;
infp->vsi_bp = bp;
infp->vsi_oltext = rsbp->vs_oltext[0];
infp->vsi_oltsize = rsbp->vs_oltsize;
if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
printk(KERN_WARNING "vxfs: unable to set final block size\n");
goto out;
}
if (vxfs_read_olt(sbp, bsize)) {
printk(KERN_WARNING "vxfs: unable to read olt\n");
goto out;
}
if (vxfs_read_fshead(sbp)) {
printk(KERN_WARNING "vxfs: unable to read fshead\n");
goto out;
}
sbp->s_op = &vxfs_super_ops;
root = iget(sbp, VXFS_ROOT_INO);
sbp->s_root = d_alloc_root(root);
if (!sbp->s_root) {
iput(root);
printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
goto out_free_ilist;
}
return 0;
out_free_ilist:
vxfs_put_fake_inode(infp->vsi_fship);
vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist);
out:
brelse(bp);
kfree(infp);
return -EINVAL;
}
/*
* The usual module blurb.
*/
static struct super_block *vxfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
}
static struct file_system_type vxfs_fs_type = {
.owner = THIS_MODULE,
.name = "vxfs",
.get_sb = vxfs_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
static int __init
vxfs_init(void)
{
vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
sizeof(struct vxfs_inode_info), 0,
SLAB_RECLAIM_ACCOUNT, NULL, NULL);
if (vxfs_inode_cachep)
return (register_filesystem(&vxfs_fs_type));
return -ENOMEM;
}
static void __exit
vxfs_cleanup(void)
{
unregister_filesystem(&vxfs_fs_type);
kmem_cache_destroy(vxfs_inode_cachep);
}
module_init(vxfs_init);
module_exit(vxfs_cleanup);