diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
| 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 000000000000..87ad097440d6 --- /dev/null +++ b/fs/freevxfs/Makefile | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # | ||
| 2 | # VxFS Makefile | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_VXFS_FS) += freevxfs.o | ||
| 6 | |||
| 7 | freevxfs-objs := vxfs_bmap.o vxfs_fshead.o vxfs_immed.o vxfs_inode.o \ | ||
| 8 | 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 000000000000..8da0252642a4 --- /dev/null +++ b/fs/freevxfs/vxfs.h | |||
| @@ -0,0 +1,264 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #ifndef _VXFS_SUPER_H_ | ||
| 31 | #define _VXFS_SUPER_H_ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Veritas filesystem driver - superblock structure. | ||
| 35 | * | ||
| 36 | * This file contains the definition of the disk and core | ||
| 37 | * superblocks of the Veritas Filesystem. | ||
| 38 | */ | ||
| 39 | #include <linux/types.h> | ||
| 40 | #include "vxfs_kcompat.h" | ||
| 41 | |||
| 42 | |||
| 43 | /* | ||
| 44 | * Data types for use with the VxFS ondisk format. | ||
| 45 | */ | ||
| 46 | typedef int32_t vx_daddr_t; | ||
| 47 | typedef int32_t vx_ino_t; | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Superblock magic number (vxfs_super->vs_magic). | ||
| 51 | */ | ||
| 52 | #define VXFS_SUPER_MAGIC 0xa501FCF5 | ||
| 53 | |||
| 54 | /* | ||
| 55 | * The root inode. | ||
| 56 | */ | ||
| 57 | #define VXFS_ROOT_INO 2 | ||
| 58 | |||
| 59 | /* | ||
| 60 | * Num of entries in free extent array | ||
| 61 | */ | ||
| 62 | #define VXFS_NEFREE 32 | ||
| 63 | |||
| 64 | |||
| 65 | /* | ||
| 66 | * VxFS superblock (disk). | ||
| 67 | */ | ||
| 68 | struct vxfs_sb { | ||
| 69 | /* | ||
| 70 | * Readonly fields for the version 1 superblock. | ||
| 71 | * | ||
| 72 | * Lots of this fields are no more used by version 2 | ||
| 73 | * and never filesystems. | ||
| 74 | */ | ||
| 75 | u_int32_t vs_magic; /* Magic number */ | ||
| 76 | int32_t vs_version; /* VxFS version */ | ||
| 77 | u_int32_t vs_ctime; /* create time - secs */ | ||
| 78 | u_int32_t vs_cutime; /* create time - usecs */ | ||
| 79 | int32_t __unused1; /* unused */ | ||
| 80 | int32_t __unused2; /* unused */ | ||
| 81 | vx_daddr_t vs_old_logstart; /* obsolete */ | ||
| 82 | vx_daddr_t vs_old_logend; /* obsolete */ | ||
| 83 | int32_t vs_bsize; /* block size */ | ||
| 84 | int32_t vs_size; /* number of blocks */ | ||
| 85 | int32_t vs_dsize; /* number of data blocks */ | ||
| 86 | u_int32_t vs_old_ninode; /* obsolete */ | ||
| 87 | int32_t vs_old_nau; /* obsolete */ | ||
| 88 | int32_t __unused3; /* unused */ | ||
| 89 | int32_t vs_old_defiextsize; /* obsolete */ | ||
| 90 | int32_t vs_old_ilbsize; /* obsolete */ | ||
| 91 | int32_t vs_immedlen; /* size of immediate data area */ | ||
| 92 | int32_t vs_ndaddr; /* number of direct extentes */ | ||
| 93 | vx_daddr_t vs_firstau; /* address of first AU */ | ||
| 94 | vx_daddr_t vs_emap; /* offset of extent map in AU */ | ||
| 95 | vx_daddr_t vs_imap; /* offset of inode map in AU */ | ||
| 96 | vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */ | ||
| 97 | vx_daddr_t vs_istart; /* offset of inode list in AU */ | ||
| 98 | vx_daddr_t vs_bstart; /* offset of fdblock in AU */ | ||
| 99 | vx_daddr_t vs_femap; /* aufirst + emap */ | ||
| 100 | vx_daddr_t vs_fimap; /* aufirst + imap */ | ||
| 101 | vx_daddr_t vs_fiextop; /* aufirst + iextop */ | ||
| 102 | vx_daddr_t vs_fistart; /* aufirst + istart */ | ||
| 103 | vx_daddr_t vs_fbstart; /* aufirst + bstart */ | ||
| 104 | int32_t vs_nindir; /* number of entries in indir */ | ||
| 105 | int32_t vs_aulen; /* length of AU in blocks */ | ||
| 106 | int32_t vs_auimlen; /* length of imap in blocks */ | ||
| 107 | int32_t vs_auemlen; /* length of emap in blocks */ | ||
| 108 | int32_t vs_auilen; /* length of ilist in blocks */ | ||
| 109 | int32_t vs_aupad; /* length of pad in blocks */ | ||
| 110 | int32_t vs_aublocks; /* data blocks in AU */ | ||
| 111 | int32_t vs_maxtier; /* log base 2 of aublocks */ | ||
| 112 | int32_t vs_inopb; /* number of inodes per blk */ | ||
| 113 | int32_t vs_old_inopau; /* obsolete */ | ||
| 114 | int32_t vs_old_inopilb; /* obsolete */ | ||
| 115 | int32_t vs_old_ndiripau; /* obsolete */ | ||
| 116 | int32_t vs_iaddrlen; /* size of indirect addr ext. */ | ||
| 117 | int32_t vs_bshift; /* log base 2 of bsize */ | ||
| 118 | int32_t vs_inoshift; /* log base 2 of inobp */ | ||
| 119 | int32_t vs_bmask; /* ~( bsize - 1 ) */ | ||
| 120 | int32_t vs_boffmask; /* bsize - 1 */ | ||
| 121 | int32_t vs_old_inomask; /* old_inopilb - 1 */ | ||
| 122 | int32_t vs_checksum; /* checksum of V1 data */ | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Version 1, writable | ||
| 126 | */ | ||
| 127 | int32_t vs_free; /* number of free blocks */ | ||
| 128 | int32_t vs_ifree; /* number of free inodes */ | ||
| 129 | int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */ | ||
| 130 | int32_t vs_flags; /* flags ?!? */ | ||
| 131 | u_int8_t vs_mod; /* filesystem has been changed */ | ||
| 132 | u_int8_t vs_clean; /* clean FS */ | ||
| 133 | u_int16_t __unused4; /* unused */ | ||
| 134 | u_int32_t vs_firstlogid; /* mount time log ID */ | ||
| 135 | u_int32_t vs_wtime; /* last time written - sec */ | ||
| 136 | u_int32_t vs_wutime; /* last time written - usec */ | ||
| 137 | u_int8_t vs_fname[6]; /* FS name */ | ||
| 138 | u_int8_t vs_fpack[6]; /* FS pack name */ | ||
| 139 | int32_t vs_logversion; /* log format version */ | ||
| 140 | int32_t __unused5; /* unused */ | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Version 2, Read-only | ||
| 144 | */ | ||
| 145 | vx_daddr_t vs_oltext[2]; /* OLT extent and replica */ | ||
| 146 | int32_t vs_oltsize; /* OLT extent size */ | ||
| 147 | int32_t vs_iauimlen; /* size of inode map */ | ||
| 148 | int32_t vs_iausize; /* size of IAU in blocks */ | ||
| 149 | int32_t vs_dinosize; /* size of inode in bytes */ | ||
| 150 | int32_t vs_old_dniaddr; /* indir levels per inode */ | ||
| 151 | int32_t vs_checksum2; /* checksum of V2 RO */ | ||
| 152 | |||
| 153 | /* | ||
| 154 | * Actually much more... | ||
| 155 | */ | ||
| 156 | }; | ||
| 157 | |||
| 158 | |||
| 159 | /* | ||
| 160 | * In core superblock filesystem private data for VxFS. | ||
| 161 | */ | ||
| 162 | struct vxfs_sb_info { | ||
| 163 | struct vxfs_sb *vsi_raw; /* raw (on disk) supeblock */ | ||
| 164 | struct buffer_head *vsi_bp; /* buffer for raw superblock*/ | ||
| 165 | struct inode *vsi_fship; /* fileset header inode */ | ||
| 166 | struct inode *vsi_ilist; /* inode list inode */ | ||
| 167 | struct inode *vsi_stilist; /* structual inode list inode */ | ||
| 168 | u_long vsi_iext; /* initial inode list */ | ||
| 169 | ino_t vsi_fshino; /* fileset header inode */ | ||
| 170 | daddr_t vsi_oltext; /* OLT extent */ | ||
| 171 | daddr_t vsi_oltsize; /* OLT size */ | ||
| 172 | }; | ||
| 173 | |||
| 174 | |||
| 175 | /* | ||
| 176 | * File modes. File types above 0xf000 are vxfs internal only, they should | ||
| 177 | * not be passed back to higher levels of the system. vxfs file types must | ||
| 178 | * never have one of the regular file type bits set. | ||
| 179 | */ | ||
| 180 | enum vxfs_mode { | ||
| 181 | VXFS_ISUID = 0x00000800, /* setuid */ | ||
| 182 | VXFS_ISGID = 0x00000400, /* setgid */ | ||
| 183 | VXFS_ISVTX = 0x00000200, /* sticky bit */ | ||
| 184 | VXFS_IREAD = 0x00000100, /* read */ | ||
| 185 | VXFS_IWRITE = 0x00000080, /* write */ | ||
| 186 | VXFS_IEXEC = 0x00000040, /* exec */ | ||
| 187 | |||
| 188 | VXFS_IFIFO = 0x00001000, /* Named pipe */ | ||
| 189 | VXFS_IFCHR = 0x00002000, /* Character device */ | ||
| 190 | VXFS_IFDIR = 0x00004000, /* Directory */ | ||
| 191 | VXFS_IFNAM = 0x00005000, /* Xenix device ?? */ | ||
| 192 | VXFS_IFBLK = 0x00006000, /* Block device */ | ||
| 193 | VXFS_IFREG = 0x00008000, /* Regular file */ | ||
| 194 | VXFS_IFCMP = 0x00009000, /* Compressed file ?!? */ | ||
| 195 | VXFS_IFLNK = 0x0000a000, /* Symlink */ | ||
| 196 | VXFS_IFSOC = 0x0000c000, /* Socket */ | ||
| 197 | |||
| 198 | /* VxFS internal */ | ||
| 199 | VXFS_IFFSH = 0x10000000, /* Fileset header */ | ||
| 200 | VXFS_IFILT = 0x20000000, /* Inode list */ | ||
| 201 | VXFS_IFIAU = 0x30000000, /* Inode allocation unit */ | ||
| 202 | VXFS_IFCUT = 0x40000000, /* Current usage table */ | ||
| 203 | VXFS_IFATT = 0x50000000, /* Attr. inode */ | ||
| 204 | VXFS_IFLCT = 0x60000000, /* Link count table */ | ||
| 205 | VXFS_IFIAT = 0x70000000, /* Indirect attribute file */ | ||
| 206 | VXFS_IFEMR = 0x80000000, /* Extent map reorg file */ | ||
| 207 | VXFS_IFQUO = 0x90000000, /* BSD quota file */ | ||
| 208 | VXFS_IFPTI = 0xa0000000, /* "Pass through" inode */ | ||
| 209 | VXFS_IFLAB = 0x11000000, /* Device label file */ | ||
| 210 | VXFS_IFOLT = 0x12000000, /* OLT file */ | ||
| 211 | VXFS_IFLOG = 0x13000000, /* Log file */ | ||
| 212 | VXFS_IFEMP = 0x14000000, /* Extent map file */ | ||
| 213 | VXFS_IFEAU = 0x15000000, /* Extent AU file */ | ||
| 214 | VXFS_IFAUS = 0x16000000, /* Extent AU summary file */ | ||
| 215 | VXFS_IFDEV = 0x17000000, /* Device config file */ | ||
| 216 | |||
| 217 | }; | ||
| 218 | |||
| 219 | #define VXFS_TYPE_MASK 0xfffff000 | ||
| 220 | |||
| 221 | #define VXFS_IS_TYPE(ip,type) (((ip)->vii_mode & VXFS_TYPE_MASK) == (type)) | ||
| 222 | #define VXFS_ISFIFO(x) VXFS_IS_TYPE((x),VXFS_IFIFO) | ||
| 223 | #define VXFS_ISCHR(x) VXFS_IS_TYPE((x),VXFS_IFCHR) | ||
| 224 | #define VXFS_ISDIR(x) VXFS_IS_TYPE((x),VXFS_IFDIR) | ||
| 225 | #define VXFS_ISNAM(x) VXFS_IS_TYPE((x),VXFS_IFNAM) | ||
| 226 | #define VXFS_ISBLK(x) VXFS_IS_TYPE((x),VXFS_IFBLK) | ||
| 227 | #define VXFS_ISLNK(x) VXFS_IS_TYPE((x),VXFS_IFLNK) | ||
| 228 | #define VXFS_ISREG(x) VXFS_IS_TYPE((x),VXFS_IFREG) | ||
| 229 | #define VXFS_ISCMP(x) VXFS_IS_TYPE((x),VXFS_IFCMP) | ||
| 230 | #define VXFS_ISSOC(x) VXFS_IS_TYPE((x),VXFS_IFSOC) | ||
| 231 | |||
| 232 | #define VXFS_ISFSH(x) VXFS_IS_TYPE((x),VXFS_IFFSH) | ||
| 233 | #define VXFS_ISILT(x) VXFS_IS_TYPE((x),VXFS_IFILT) | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Inmode organisation types. | ||
| 237 | */ | ||
| 238 | enum { | ||
| 239 | VXFS_ORG_NONE = 0, /* Inode has *no* format ?!? */ | ||
| 240 | VXFS_ORG_EXT4 = 1, /* Ext4 */ | ||
| 241 | VXFS_ORG_IMMED = 2, /* All data stored in inode */ | ||
| 242 | VXFS_ORG_TYPED = 3, /* Typed extents */ | ||
| 243 | }; | ||
| 244 | |||
| 245 | #define VXFS_IS_ORG(ip,org) ((ip)->vii_orgtype == (org)) | ||
| 246 | #define VXFS_ISNONE(ip) VXFS_IS_ORG((ip), VXFS_ORG_NONE) | ||
| 247 | #define VXFS_ISEXT4(ip) VXFS_IS_ORG((ip), VXFS_ORG_EXT4) | ||
| 248 | #define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) | ||
| 249 | #define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) | ||
| 250 | |||
| 251 | |||
| 252 | /* | ||
| 253 | * Get filesystem private data from VFS inode. | ||
| 254 | */ | ||
| 255 | #define VXFS_INO(ip) \ | ||
| 256 | ((struct vxfs_inode_info *)(ip)->u.generic_ip) | ||
| 257 | |||
| 258 | /* | ||
| 259 | * Get filesystem private data from VFS superblock. | ||
| 260 | */ | ||
| 261 | #define VXFS_SBI(sbp) \ | ||
| 262 | ((struct vxfs_sb_info *)(sbp)->s_fs_info) | ||
| 263 | |||
| 264 | #endif /* _VXFS_SUPER_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c new file mode 100644 index 000000000000..bc4b57da306a --- /dev/null +++ b/fs/freevxfs/vxfs_bmap.c | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - filesystem to disk block mapping. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/buffer_head.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | |||
| 37 | #include "vxfs.h" | ||
| 38 | #include "vxfs_inode.h" | ||
| 39 | |||
| 40 | |||
| 41 | #ifdef DIAGNOSTIC | ||
| 42 | static void | ||
| 43 | vxfs_typdump(struct vxfs_typed *typ) | ||
| 44 | { | ||
| 45 | printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT); | ||
| 46 | printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK); | ||
| 47 | printk("block=%x ", typ->vt_block); | ||
| 48 | printk("size=%x\n", typ->vt_size); | ||
| 49 | } | ||
| 50 | #endif | ||
| 51 | |||
| 52 | /** | ||
| 53 | * vxfs_bmap_ext4 - do bmap for ext4 extents | ||
| 54 | * @ip: pointer to the inode we do bmap for | ||
| 55 | * @iblock: logical block. | ||
| 56 | * | ||
| 57 | * Description: | ||
| 58 | * vxfs_bmap_ext4 performs the bmap operation for inodes with | ||
| 59 | * ext4-style extents (which are much like the traditional UNIX | ||
| 60 | * inode organisation). | ||
| 61 | * | ||
| 62 | * Returns: | ||
| 63 | * The physical block number on success, else Zero. | ||
| 64 | */ | ||
| 65 | static daddr_t | ||
| 66 | vxfs_bmap_ext4(struct inode *ip, long bn) | ||
| 67 | { | ||
| 68 | struct super_block *sb = ip->i_sb; | ||
| 69 | struct vxfs_inode_info *vip = VXFS_INO(ip); | ||
| 70 | unsigned long bsize = sb->s_blocksize; | ||
| 71 | u32 indsize = vip->vii_ext4.ve4_indsize; | ||
| 72 | int i; | ||
| 73 | |||
| 74 | if (indsize > sb->s_blocksize) | ||
| 75 | goto fail_size; | ||
| 76 | |||
| 77 | for (i = 0; i < VXFS_NDADDR; i++) { | ||
| 78 | struct direct *d = vip->vii_ext4.ve4_direct + i; | ||
| 79 | if (bn >= 0 && bn < d->size) | ||
| 80 | return (bn + d->extent); | ||
| 81 | bn -= d->size; | ||
| 82 | } | ||
| 83 | |||
| 84 | if ((bn / (indsize * indsize * bsize / 4)) == 0) { | ||
| 85 | struct buffer_head *buf; | ||
| 86 | daddr_t bno; | ||
| 87 | u32 *indir; | ||
| 88 | |||
| 89 | buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]); | ||
| 90 | if (!buf || !buffer_mapped(buf)) | ||
| 91 | goto fail_buf; | ||
| 92 | |||
| 93 | indir = (u32 *)buf->b_data; | ||
| 94 | bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize); | ||
| 95 | |||
| 96 | brelse(buf); | ||
| 97 | return bno; | ||
| 98 | } else | ||
| 99 | printk(KERN_WARNING "no matching indir?"); | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | |||
| 103 | fail_size: | ||
| 104 | printk("vxfs: indirect extent to big!\n"); | ||
| 105 | fail_buf: | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | /** | ||
| 110 | * vxfs_bmap_indir - recursion for vxfs_bmap_typed | ||
| 111 | * @ip: pointer to the inode we do bmap for | ||
| 112 | * @indir: indirect block we start reading at | ||
| 113 | * @size: size of the typed area to search | ||
| 114 | * @block: partially result from further searches | ||
| 115 | * | ||
| 116 | * Description: | ||
| 117 | * vxfs_bmap_indir reads a &struct vxfs_typed at @indir | ||
| 118 | * and performs the type-defined action. | ||
| 119 | * | ||
| 120 | * Return Value: | ||
| 121 | * The physical block number on success, else Zero. | ||
| 122 | * | ||
| 123 | * Note: | ||
| 124 | * Kernelstack is rare. Unrecurse? | ||
| 125 | */ | ||
| 126 | static daddr_t | ||
| 127 | vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) | ||
| 128 | { | ||
| 129 | struct buffer_head *bp = NULL; | ||
| 130 | daddr_t pblock = 0; | ||
| 131 | int i; | ||
| 132 | |||
| 133 | for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) { | ||
| 134 | struct vxfs_typed *typ; | ||
| 135 | int64_t off; | ||
| 136 | |||
| 137 | bp = sb_bread(ip->i_sb, | ||
| 138 | indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb))); | ||
| 139 | if (!buffer_mapped(bp)) | ||
| 140 | return 0; | ||
| 141 | |||
| 142 | typ = ((struct vxfs_typed *)bp->b_data) + | ||
| 143 | (i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); | ||
| 144 | off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); | ||
| 145 | |||
| 146 | if (block < off) { | ||
| 147 | brelse(bp); | ||
| 148 | continue; | ||
| 149 | } | ||
| 150 | |||
| 151 | switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { | ||
| 152 | case VXFS_TYPED_INDIRECT: | ||
| 153 | pblock = vxfs_bmap_indir(ip, typ->vt_block, | ||
| 154 | typ->vt_size, block - off); | ||
| 155 | if (pblock == -2) | ||
| 156 | break; | ||
| 157 | goto out; | ||
| 158 | case VXFS_TYPED_DATA: | ||
| 159 | if ((block - off) >= typ->vt_size) | ||
| 160 | break; | ||
| 161 | pblock = (typ->vt_block + block - off); | ||
| 162 | goto out; | ||
| 163 | case VXFS_TYPED_INDIRECT_DEV4: | ||
| 164 | case VXFS_TYPED_DATA_DEV4: { | ||
| 165 | struct vxfs_typed_dev4 *typ4 = | ||
| 166 | (struct vxfs_typed_dev4 *)typ; | ||
| 167 | |||
| 168 | printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); | ||
| 169 | printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", | ||
| 170 | (unsigned long long) typ4->vd4_block, | ||
| 171 | (unsigned long long) typ4->vd4_size, | ||
| 172 | typ4->vd4_dev); | ||
| 173 | goto fail; | ||
| 174 | } | ||
| 175 | default: | ||
| 176 | BUG(); | ||
| 177 | } | ||
| 178 | brelse(bp); | ||
| 179 | } | ||
| 180 | |||
| 181 | fail: | ||
| 182 | pblock = 0; | ||
| 183 | out: | ||
| 184 | brelse(bp); | ||
| 185 | return (pblock); | ||
| 186 | } | ||
| 187 | |||
| 188 | /** | ||
| 189 | * vxfs_bmap_typed - bmap for typed extents | ||
| 190 | * @ip: pointer to the inode we do bmap for | ||
| 191 | * @iblock: logical block | ||
| 192 | * | ||
| 193 | * Description: | ||
| 194 | * Performs the bmap operation for typed extents. | ||
| 195 | * | ||
| 196 | * Return Value: | ||
| 197 | * The physical block number on success, else Zero. | ||
| 198 | */ | ||
| 199 | static daddr_t | ||
| 200 | vxfs_bmap_typed(struct inode *ip, long iblock) | ||
| 201 | { | ||
| 202 | struct vxfs_inode_info *vip = VXFS_INO(ip); | ||
| 203 | daddr_t pblock = 0; | ||
| 204 | int i; | ||
| 205 | |||
| 206 | for (i = 0; i < VXFS_NTYPED; i++) { | ||
| 207 | struct vxfs_typed *typ = vip->vii_org.typed + i; | ||
| 208 | int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); | ||
| 209 | |||
| 210 | #ifdef DIAGNOSTIC | ||
| 211 | vxfs_typdump(typ); | ||
| 212 | #endif | ||
| 213 | if (iblock < off) | ||
| 214 | continue; | ||
| 215 | switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { | ||
| 216 | case VXFS_TYPED_INDIRECT: | ||
| 217 | pblock = vxfs_bmap_indir(ip, typ->vt_block, | ||
| 218 | typ->vt_size, iblock - off); | ||
| 219 | if (pblock == -2) | ||
| 220 | break; | ||
| 221 | return (pblock); | ||
| 222 | case VXFS_TYPED_DATA: | ||
| 223 | if ((iblock - off) < typ->vt_size) | ||
| 224 | return (typ->vt_block + iblock - off); | ||
| 225 | break; | ||
| 226 | case VXFS_TYPED_INDIRECT_DEV4: | ||
| 227 | case VXFS_TYPED_DATA_DEV4: { | ||
| 228 | struct vxfs_typed_dev4 *typ4 = | ||
| 229 | (struct vxfs_typed_dev4 *)typ; | ||
| 230 | |||
| 231 | printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); | ||
| 232 | printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", | ||
| 233 | (unsigned long long) typ4->vd4_block, | ||
| 234 | (unsigned long long) typ4->vd4_size, | ||
| 235 | typ4->vd4_dev); | ||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | default: | ||
| 239 | BUG(); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | /** | ||
| 247 | * vxfs_bmap1 - vxfs-internal bmap operation | ||
| 248 | * @ip: pointer to the inode we do bmap for | ||
| 249 | * @iblock: logical block | ||
| 250 | * | ||
| 251 | * Description: | ||
| 252 | * vxfs_bmap1 perfoms a logical to physical block mapping | ||
| 253 | * for vxfs-internal purposes. | ||
| 254 | * | ||
| 255 | * Return Value: | ||
| 256 | * The physical block number on success, else Zero. | ||
| 257 | */ | ||
| 258 | daddr_t | ||
| 259 | vxfs_bmap1(struct inode *ip, long iblock) | ||
| 260 | { | ||
| 261 | struct vxfs_inode_info *vip = VXFS_INO(ip); | ||
| 262 | |||
| 263 | if (VXFS_ISEXT4(vip)) | ||
| 264 | return vxfs_bmap_ext4(ip, iblock); | ||
| 265 | if (VXFS_ISTYPED(vip)) | ||
| 266 | return vxfs_bmap_typed(ip, iblock); | ||
| 267 | if (VXFS_ISNONE(vip)) | ||
| 268 | goto unsupp; | ||
| 269 | if (VXFS_ISIMMED(vip)) | ||
| 270 | goto unsupp; | ||
| 271 | |||
| 272 | printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n", | ||
| 273 | ip->i_ino, vip->vii_orgtype); | ||
| 274 | BUG(); | ||
| 275 | |||
| 276 | unsupp: | ||
| 277 | printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n", | ||
| 278 | ip->i_ino, vip->vii_orgtype); | ||
| 279 | return 0; | ||
| 280 | } | ||
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h new file mode 100644 index 000000000000..8a4dfef1ddad --- /dev/null +++ b/fs/freevxfs/vxfs_dir.h | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #ifndef _VXFS_DIR_H_ | ||
| 31 | #define _VXFS_DIR_H_ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Veritas filesystem driver - directory structure. | ||
| 35 | * | ||
| 36 | * This file contains the definition of the vxfs directory format. | ||
| 37 | */ | ||
| 38 | |||
| 39 | |||
| 40 | /* | ||
| 41 | * VxFS directory block header. | ||
| 42 | * | ||
| 43 | * This entry is the head of every filesystem block in a directory. | ||
| 44 | * It is used for free space managment and additionally includes | ||
| 45 | * a hash for speeding up directory search (lookup). | ||
| 46 | * | ||
| 47 | * The hash may be empty and in fact we do not use it all in the | ||
| 48 | * Linux driver for now. | ||
| 49 | */ | ||
| 50 | struct vxfs_dirblk { | ||
| 51 | u_int16_t d_free; /* free space in dirblock */ | ||
| 52 | u_int16_t d_nhash; /* no of hash chains */ | ||
| 53 | u_int16_t d_hash[1]; /* hash chain */ | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * VXFS_NAMELEN is the maximum length of the d_name field | ||
| 58 | * of an VxFS directory entry. | ||
| 59 | */ | ||
| 60 | #define VXFS_NAMELEN 256 | ||
| 61 | |||
| 62 | /* | ||
| 63 | * VxFS directory entry. | ||
| 64 | */ | ||
| 65 | struct vxfs_direct { | ||
| 66 | vx_ino_t d_ino; /* inode number */ | ||
| 67 | u_int16_t d_reclen; /* record length */ | ||
| 68 | u_int16_t d_namelen; /* d_name length */ | ||
| 69 | u_int16_t d_hashnext; /* next hash entry */ | ||
| 70 | char d_name[VXFS_NAMELEN]; /* name */ | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * VXFS_DIRPAD defines the directory entry boundaries, is _must_ be | ||
| 75 | * a multiple of four. | ||
| 76 | * VXFS_NAMEMIN is the length of a directory entry with a NULL d_name. | ||
| 77 | * VXFS_DIRROUND is an internal macros that rounds a length to a value | ||
| 78 | * usable for directory sizes. | ||
| 79 | * VXFS_DIRLEN calculates the directory entry size for an entry with | ||
| 80 | * a d_name with size len. | ||
| 81 | */ | ||
| 82 | #define VXFS_DIRPAD 4 | ||
| 83 | #define VXFS_NAMEMIN ((int)((struct vxfs_direct *)0)->d_name) | ||
| 84 | #define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1)) | ||
| 85 | #define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len))) | ||
| 86 | |||
| 87 | /* | ||
| 88 | * VXFS_DIRBLKOV is the overhead of a specific dirblock. | ||
| 89 | */ | ||
| 90 | #define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4) | ||
| 91 | |||
| 92 | #endif /* _VXFS_DIR_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h new file mode 100644 index 000000000000..d8be917f9797 --- /dev/null +++ b/fs/freevxfs/vxfs_extern.h | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #ifndef _VXFS_EXTERN_H_ | ||
| 31 | #define _VXFS_EXTERN_H_ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Veritas filesystem driver - external prototypes. | ||
| 35 | * | ||
| 36 | * This file contains prototypes for all vxfs functions used | ||
| 37 | * outside their respective source files. | ||
| 38 | */ | ||
| 39 | |||
| 40 | |||
| 41 | struct kmem_cache_s; | ||
| 42 | struct super_block; | ||
| 43 | struct vxfs_inode_info; | ||
| 44 | struct inode; | ||
| 45 | |||
| 46 | |||
| 47 | /* vxfs_bmap.c */ | ||
| 48 | extern daddr_t vxfs_bmap1(struct inode *, long); | ||
| 49 | |||
| 50 | /* vxfs_fshead.c */ | ||
| 51 | extern int vxfs_read_fshead(struct super_block *); | ||
| 52 | |||
| 53 | /* vxfs_inode.c */ | ||
| 54 | extern struct kmem_cache_s *vxfs_inode_cachep; | ||
| 55 | extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); | ||
| 56 | extern struct inode * vxfs_get_fake_inode(struct super_block *, | ||
| 57 | struct vxfs_inode_info *); | ||
| 58 | extern void vxfs_put_fake_inode(struct inode *); | ||
| 59 | extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); | ||
| 60 | extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); | ||
| 61 | extern void vxfs_read_inode(struct inode *); | ||
| 62 | extern void vxfs_clear_inode(struct inode *); | ||
| 63 | |||
| 64 | /* vxfs_lookup.c */ | ||
| 65 | extern struct inode_operations vxfs_dir_inode_ops; | ||
| 66 | extern struct file_operations vxfs_dir_operations; | ||
| 67 | |||
| 68 | /* vxfs_olt.c */ | ||
| 69 | extern int vxfs_read_olt(struct super_block *, u_long); | ||
| 70 | |||
| 71 | /* vxfs_subr.c */ | ||
| 72 | extern struct page * vxfs_get_page(struct address_space *, u_long); | ||
| 73 | extern void vxfs_put_page(struct page *); | ||
| 74 | extern struct buffer_head * vxfs_bread(struct inode *, int); | ||
| 75 | |||
| 76 | #endif /* _VXFS_EXTERN_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c new file mode 100644 index 000000000000..05b19f70bf97 --- /dev/null +++ b/fs/freevxfs/vxfs_fshead.c | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - fileset header routines. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/buffer_head.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/string.h> | ||
| 38 | |||
| 39 | #include "vxfs.h" | ||
| 40 | #include "vxfs_inode.h" | ||
| 41 | #include "vxfs_extern.h" | ||
| 42 | #include "vxfs_fshead.h" | ||
| 43 | |||
| 44 | |||
| 45 | #ifdef DIAGNOSTIC | ||
| 46 | static void | ||
| 47 | vxfs_dumpfsh(struct vxfs_fsh *fhp) | ||
| 48 | { | ||
| 49 | printk("\n\ndumping fileset header:\n"); | ||
| 50 | printk("----------------------------\n"); | ||
| 51 | printk("version: %u\n", fhp->fsh_version); | ||
| 52 | printk("fsindex: %u\n", fhp->fsh_fsindex); | ||
| 53 | printk("iauino: %u\tninodes:%u\n", | ||
| 54 | fhp->fsh_iauino, fhp->fsh_ninodes); | ||
| 55 | printk("maxinode: %u\tlctino: %u\n", | ||
| 56 | fhp->fsh_maxinode, fhp->fsh_lctino); | ||
| 57 | printk("nau: %u\n", fhp->fsh_nau); | ||
| 58 | printk("ilistino[0]: %u\tilistino[1]: %u\n", | ||
| 59 | fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]); | ||
| 60 | } | ||
| 61 | #endif | ||
| 62 | |||
| 63 | /** | ||
| 64 | * vxfs_getfsh - read fileset header into memory | ||
| 65 | * @ip: the (fake) fileset header inode | ||
| 66 | * @which: 0 for the structural, 1 for the primary fsh. | ||
| 67 | * | ||
| 68 | * Description: | ||
| 69 | * vxfs_getfsh reads either the structural or primary fileset header | ||
| 70 | * described by @ip into memory. | ||
| 71 | * | ||
| 72 | * Returns: | ||
| 73 | * The fileset header structure on success, else Zero. | ||
| 74 | */ | ||
| 75 | static struct vxfs_fsh * | ||
| 76 | vxfs_getfsh(struct inode *ip, int which) | ||
| 77 | { | ||
| 78 | struct buffer_head *bp; | ||
| 79 | |||
| 80 | bp = vxfs_bread(ip, which); | ||
| 81 | if (buffer_mapped(bp)) { | ||
| 82 | struct vxfs_fsh *fhp; | ||
| 83 | |||
| 84 | if (!(fhp = kmalloc(sizeof(*fhp), SLAB_KERNEL))) | ||
| 85 | return NULL; | ||
| 86 | memcpy(fhp, bp->b_data, sizeof(*fhp)); | ||
| 87 | |||
| 88 | brelse(bp); | ||
| 89 | return (fhp); | ||
| 90 | } | ||
| 91 | |||
| 92 | return NULL; | ||
| 93 | } | ||
| 94 | |||
| 95 | /** | ||
| 96 | * vxfs_read_fshead - read the fileset headers | ||
| 97 | * @sbp: superblock to which the fileset belongs | ||
| 98 | * | ||
| 99 | * Description: | ||
| 100 | * vxfs_read_fshead will fill the inode and structural inode list in @sb. | ||
| 101 | * | ||
| 102 | * Returns: | ||
| 103 | * Zero on success, else a negative error code (-EINVAL). | ||
| 104 | */ | ||
| 105 | int | ||
| 106 | vxfs_read_fshead(struct super_block *sbp) | ||
| 107 | { | ||
| 108 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
| 109 | struct vxfs_fsh *pfp, *sfp; | ||
| 110 | struct vxfs_inode_info *vip, *tip; | ||
| 111 | |||
| 112 | vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); | ||
| 113 | if (!vip) { | ||
| 114 | printk(KERN_ERR "vxfs: unabled to read fsh inode\n"); | ||
| 115 | return -EINVAL; | ||
| 116 | } | ||
| 117 | if (!VXFS_ISFSH(vip)) { | ||
| 118 | printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", | ||
| 119 | vip->vii_mode & VXFS_TYPE_MASK); | ||
| 120 | goto out_free_fship; | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | #ifdef DIAGNOSTIC | ||
| 125 | printk("vxfs: fsh inode dump:\n"); | ||
| 126 | vxfs_dumpi(vip, infp->vsi_fshino); | ||
| 127 | #endif | ||
| 128 | |||
| 129 | infp->vsi_fship = vxfs_get_fake_inode(sbp, vip); | ||
| 130 | if (!infp->vsi_fship) { | ||
| 131 | printk(KERN_ERR "vxfs: unabled to get fsh inode\n"); | ||
| 132 | goto out_free_fship; | ||
| 133 | } | ||
| 134 | |||
| 135 | sfp = vxfs_getfsh(infp->vsi_fship, 0); | ||
| 136 | if (!sfp) { | ||
| 137 | printk(KERN_ERR "vxfs: unabled to get structural fsh\n"); | ||
| 138 | goto out_iput_fship; | ||
| 139 | } | ||
| 140 | |||
| 141 | #ifdef DIAGNOSTIC | ||
| 142 | vxfs_dumpfsh(sfp); | ||
| 143 | #endif | ||
| 144 | |||
| 145 | pfp = vxfs_getfsh(infp->vsi_fship, 1); | ||
| 146 | if (!pfp) { | ||
| 147 | printk(KERN_ERR "vxfs: unabled to get primary fsh\n"); | ||
| 148 | goto out_free_sfp; | ||
| 149 | } | ||
| 150 | |||
| 151 | #ifdef DIAGNOSTIC | ||
| 152 | vxfs_dumpfsh(pfp); | ||
| 153 | #endif | ||
| 154 | |||
| 155 | tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); | ||
| 156 | if (!tip) | ||
| 157 | goto out_free_pfp; | ||
| 158 | |||
| 159 | infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip); | ||
| 160 | if (!infp->vsi_stilist) { | ||
| 161 | printk(KERN_ERR "vxfs: unabled to get structual list inode\n"); | ||
| 162 | kfree(tip); | ||
| 163 | goto out_free_pfp; | ||
| 164 | } | ||
| 165 | if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { | ||
| 166 | printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", | ||
| 167 | VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); | ||
| 168 | goto out_iput_stilist; | ||
| 169 | } | ||
| 170 | |||
| 171 | tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); | ||
| 172 | if (!tip) | ||
| 173 | goto out_iput_stilist; | ||
| 174 | infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); | ||
| 175 | if (!infp->vsi_ilist) { | ||
| 176 | printk(KERN_ERR "vxfs: unabled to get inode list inode\n"); | ||
| 177 | kfree(tip); | ||
| 178 | goto out_iput_stilist; | ||
| 179 | } | ||
| 180 | if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { | ||
| 181 | printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", | ||
| 182 | VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); | ||
| 183 | goto out_iput_ilist; | ||
| 184 | } | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | |||
| 188 | out_iput_ilist: | ||
| 189 | iput(infp->vsi_ilist); | ||
| 190 | out_iput_stilist: | ||
| 191 | iput(infp->vsi_stilist); | ||
| 192 | out_free_pfp: | ||
| 193 | kfree(pfp); | ||
| 194 | out_free_sfp: | ||
| 195 | kfree(sfp); | ||
| 196 | out_iput_fship: | ||
| 197 | iput(infp->vsi_fship); | ||
| 198 | return -EINVAL; | ||
| 199 | out_free_fship: | ||
| 200 | kfree(vip); | ||
| 201 | return -EINVAL; | ||
| 202 | } | ||
diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h new file mode 100644 index 000000000000..ead0d640c181 --- /dev/null +++ b/fs/freevxfs/vxfs_fshead.h | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #ifndef _VXFS_FSHEAD_H_ | ||
| 31 | #define _VXFS_FSHEAD_H_ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Veritas filesystem driver - fileset header structures. | ||
| 35 | * | ||
| 36 | * This file contains the physical structure of the VxFS | ||
| 37 | * fileset header. | ||
| 38 | */ | ||
| 39 | |||
| 40 | |||
| 41 | /* | ||
| 42 | * Fileset header | ||
| 43 | */ | ||
| 44 | struct vxfs_fsh { | ||
| 45 | u_int32_t fsh_version; /* fileset header version */ | ||
| 46 | u_int32_t fsh_fsindex; /* fileset index */ | ||
| 47 | u_int32_t fsh_time; /* modification time - sec */ | ||
| 48 | u_int32_t fsh_utime; /* modification time - usec */ | ||
| 49 | u_int32_t fsh_extop; /* extop flags */ | ||
| 50 | vx_ino_t fsh_ninodes; /* allocated inodes */ | ||
| 51 | u_int32_t fsh_nau; /* number of IAUs */ | ||
| 52 | u_int32_t fsh_old_ilesize; /* old size of ilist */ | ||
| 53 | u_int32_t fsh_dflags; /* flags */ | ||
| 54 | u_int32_t fsh_quota; /* quota limit */ | ||
| 55 | vx_ino_t fsh_maxinode; /* maximum inode number */ | ||
| 56 | vx_ino_t fsh_iauino; /* IAU inode */ | ||
| 57 | vx_ino_t fsh_ilistino[2]; /* ilist inodes */ | ||
| 58 | vx_ino_t fsh_lctino; /* link count table inode */ | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Slightly more fields follow, but they | ||
| 62 | * a) are not of any interest for us, and | ||
| 63 | * b) differ a lot in different vxfs versions/ports | ||
| 64 | */ | ||
| 65 | }; | ||
| 66 | |||
| 67 | #endif /* _VXFS_FSHEAD_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c new file mode 100644 index 000000000000..ac677ab262b2 --- /dev/null +++ b/fs/freevxfs/vxfs_immed.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - support for 'immed' inodes. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/pagemap.h> | ||
| 35 | #include <linux/namei.h> | ||
| 36 | |||
| 37 | #include "vxfs.h" | ||
| 38 | #include "vxfs_inode.h" | ||
| 39 | |||
| 40 | |||
| 41 | static int vxfs_immed_follow_link(struct dentry *, struct nameidata *); | ||
| 42 | |||
| 43 | static int vxfs_immed_readpage(struct file *, struct page *); | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Inode operations for immed symlinks. | ||
| 47 | * | ||
| 48 | * Unliked all other operations we do not go through the pagecache, | ||
| 49 | * but do all work directly on the inode. | ||
| 50 | */ | ||
| 51 | struct inode_operations vxfs_immed_symlink_iops = { | ||
| 52 | .readlink = generic_readlink, | ||
| 53 | .follow_link = vxfs_immed_follow_link, | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Adress space operations for immed files and directories. | ||
| 58 | */ | ||
| 59 | struct address_space_operations vxfs_immed_aops = { | ||
| 60 | .readpage = vxfs_immed_readpage, | ||
| 61 | }; | ||
| 62 | |||
| 63 | /** | ||
| 64 | * vxfs_immed_follow_link - follow immed symlink | ||
| 65 | * @dp: dentry for the link | ||
| 66 | * @np: pathname lookup data for the current path walk | ||
| 67 | * | ||
| 68 | * Description: | ||
| 69 | * vxfs_immed_follow_link restarts the pathname lookup with | ||
| 70 | * the data obtained from @dp. | ||
| 71 | * | ||
| 72 | * Returns: | ||
| 73 | * Zero on success, else a negative error code. | ||
| 74 | */ | ||
| 75 | static int | ||
| 76 | vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np) | ||
| 77 | { | ||
| 78 | struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); | ||
| 79 | nd_set_link(np, vip->vii_immed.vi_immed); | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | /** | ||
| 84 | * vxfs_immed_readpage - read part of an immed inode into pagecache | ||
| 85 | * @file: file context (unused) | ||
| 86 | * @page: page frame to fill in. | ||
| 87 | * | ||
| 88 | * Description: | ||
| 89 | * vxfs_immed_readpage reads a part of the immed area of the | ||
| 90 | * file that hosts @pp into the pagecache. | ||
| 91 | * | ||
| 92 | * Returns: | ||
| 93 | * Zero on success, else a negative error code. | ||
| 94 | * | ||
| 95 | * Locking status: | ||
| 96 | * @page is locked and will be unlocked. | ||
| 97 | */ | ||
| 98 | static int | ||
| 99 | vxfs_immed_readpage(struct file *fp, struct page *pp) | ||
| 100 | { | ||
| 101 | struct vxfs_inode_info *vip = VXFS_INO(pp->mapping->host); | ||
| 102 | u_int64_t offset = pp->index << PAGE_CACHE_SHIFT; | ||
| 103 | caddr_t kaddr; | ||
| 104 | |||
| 105 | kaddr = kmap(pp); | ||
| 106 | memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE); | ||
| 107 | kunmap(pp); | ||
| 108 | |||
| 109 | flush_dcache_page(pp); | ||
| 110 | SetPageUptodate(pp); | ||
| 111 | unlock_page(pp); | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c new file mode 100644 index 000000000000..9672d2facffe --- /dev/null +++ b/fs/freevxfs/vxfs_inode.c | |||
| @@ -0,0 +1,351 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - inode routines. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/buffer_head.h> | ||
| 35 | #include <linux/pagemap.h> | ||
| 36 | #include <linux/kernel.h> | ||
| 37 | #include <linux/slab.h> | ||
| 38 | |||
| 39 | #include "vxfs.h" | ||
| 40 | #include "vxfs_inode.h" | ||
| 41 | #include "vxfs_extern.h" | ||
| 42 | |||
| 43 | |||
| 44 | extern struct address_space_operations vxfs_aops; | ||
| 45 | extern struct address_space_operations vxfs_immed_aops; | ||
| 46 | |||
| 47 | extern struct inode_operations vxfs_immed_symlink_iops; | ||
| 48 | |||
| 49 | static struct file_operations vxfs_file_operations = { | ||
| 50 | .open = generic_file_open, | ||
| 51 | .llseek = generic_file_llseek, | ||
| 52 | .read = generic_file_read, | ||
| 53 | .mmap = generic_file_mmap, | ||
| 54 | .sendfile = generic_file_sendfile, | ||
| 55 | }; | ||
| 56 | |||
| 57 | |||
| 58 | kmem_cache_t *vxfs_inode_cachep; | ||
| 59 | |||
| 60 | |||
| 61 | #ifdef DIAGNOSTIC | ||
| 62 | /* | ||
| 63 | * Dump inode contents (partially). | ||
| 64 | */ | ||
| 65 | void | ||
| 66 | vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) | ||
| 67 | { | ||
| 68 | printk(KERN_DEBUG "\n\n"); | ||
| 69 | if (ino) | ||
| 70 | printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino); | ||
| 71 | else | ||
| 72 | printk(KERN_DEBUG "dumping unknown vxfs inode\n"); | ||
| 73 | |||
| 74 | printk(KERN_DEBUG "---------------------------\n"); | ||
| 75 | printk(KERN_DEBUG "mode is %x\n", vip->vii_mode); | ||
| 76 | printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n", | ||
| 77 | vip->vii_nlink, vip->vii_uid, vip->vii_gid); | ||
| 78 | printk(KERN_DEBUG "size:%Lx, blocks:%u\n", | ||
| 79 | vip->vii_size, vip->vii_blocks); | ||
| 80 | printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype); | ||
| 81 | } | ||
| 82 | #endif | ||
| 83 | |||
| 84 | |||
| 85 | /** | ||
| 86 | * vxfs_blkiget - find inode based on extent # | ||
| 87 | * @sbp: superblock of the filesystem we search in | ||
| 88 | * @extent: number of the extent to search | ||
| 89 | * @ino: inode number to search | ||
| 90 | * | ||
| 91 | * Description: | ||
| 92 | * vxfs_blkiget searches inode @ino in the filesystem described by | ||
| 93 | * @sbp in the extent @extent. | ||
| 94 | * Returns the matching VxFS inode on success, else a NULL pointer. | ||
| 95 | * | ||
| 96 | * NOTE: | ||
| 97 | * While __vxfs_iget uses the pagecache vxfs_blkiget uses the | ||
| 98 | * buffercache. This function should not be used outside the | ||
| 99 | * read_super() method, otherwise the data may be incoherent. | ||
| 100 | */ | ||
| 101 | struct vxfs_inode_info * | ||
| 102 | vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) | ||
| 103 | { | ||
| 104 | struct buffer_head *bp; | ||
| 105 | u_long block, offset; | ||
| 106 | |||
| 107 | block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); | ||
| 108 | offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); | ||
| 109 | bp = sb_bread(sbp, block); | ||
| 110 | |||
| 111 | if (buffer_mapped(bp)) { | ||
| 112 | struct vxfs_inode_info *vip; | ||
| 113 | struct vxfs_dinode *dip; | ||
| 114 | |||
| 115 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL))) | ||
| 116 | goto fail; | ||
| 117 | dip = (struct vxfs_dinode *)(bp->b_data + offset); | ||
| 118 | memcpy(vip, dip, sizeof(*vip)); | ||
| 119 | #ifdef DIAGNOSTIC | ||
| 120 | vxfs_dumpi(vip, ino); | ||
| 121 | #endif | ||
| 122 | brelse(bp); | ||
| 123 | return (vip); | ||
| 124 | } | ||
| 125 | |||
| 126 | fail: | ||
| 127 | printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); | ||
| 128 | brelse(bp); | ||
| 129 | return NULL; | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * __vxfs_iget - generic find inode facility | ||
| 134 | * @sbp: VFS superblock | ||
| 135 | * @ino: inode number | ||
| 136 | * @ilistp: inode list | ||
| 137 | * | ||
| 138 | * Description: | ||
| 139 | * Search the for inode number @ino in the filesystem | ||
| 140 | * described by @sbp. Use the specified inode table (@ilistp). | ||
| 141 | * Returns the matching VxFS inode on success, else a NULL pointer. | ||
| 142 | */ | ||
| 143 | static struct vxfs_inode_info * | ||
| 144 | __vxfs_iget(ino_t ino, struct inode *ilistp) | ||
| 145 | { | ||
| 146 | struct page *pp; | ||
| 147 | u_long offset; | ||
| 148 | |||
| 149 | offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; | ||
| 150 | pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); | ||
| 151 | |||
| 152 | if (!IS_ERR(pp)) { | ||
| 153 | struct vxfs_inode_info *vip; | ||
| 154 | struct vxfs_dinode *dip; | ||
| 155 | caddr_t kaddr = (char *)page_address(pp); | ||
| 156 | |||
| 157 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL))) | ||
| 158 | goto fail; | ||
| 159 | dip = (struct vxfs_dinode *)(kaddr + offset); | ||
| 160 | memcpy(vip, dip, sizeof(*vip)); | ||
| 161 | #ifdef DIAGNOSTIC | ||
| 162 | vxfs_dumpi(vip, ino); | ||
| 163 | #endif | ||
| 164 | vxfs_put_page(pp); | ||
| 165 | return (vip); | ||
| 166 | } | ||
| 167 | |||
| 168 | printk(KERN_WARNING "vxfs: error on page %p\n", pp); | ||
| 169 | return NULL; | ||
| 170 | |||
| 171 | fail: | ||
| 172 | printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); | ||
| 173 | vxfs_put_page(pp); | ||
| 174 | return NULL; | ||
| 175 | } | ||
| 176 | |||
| 177 | /** | ||
| 178 | * vxfs_stiget - find inode using the structural inode list | ||
| 179 | * @sbp: VFS superblock | ||
| 180 | * @ino: inode # | ||
| 181 | * | ||
| 182 | * Description: | ||
| 183 | * Find inode @ino in the filesystem described by @sbp using | ||
| 184 | * the structural inode list. | ||
| 185 | * Returns the matching VxFS inode on success, else a NULL pointer. | ||
| 186 | */ | ||
| 187 | struct vxfs_inode_info * | ||
| 188 | vxfs_stiget(struct super_block *sbp, ino_t ino) | ||
| 189 | { | ||
| 190 | return __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * vxfs_transmod - mode for a VxFS inode | ||
| 195 | * @vip: VxFS inode | ||
| 196 | * | ||
| 197 | * Description: | ||
| 198 | * vxfs_transmod returns a Linux mode_t for a given | ||
| 199 | * VxFS inode structure. | ||
| 200 | */ | ||
| 201 | static __inline__ mode_t | ||
| 202 | vxfs_transmod(struct vxfs_inode_info *vip) | ||
| 203 | { | ||
| 204 | mode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; | ||
| 205 | |||
| 206 | if (VXFS_ISFIFO(vip)) | ||
| 207 | ret |= S_IFIFO; | ||
| 208 | if (VXFS_ISCHR(vip)) | ||
| 209 | ret |= S_IFCHR; | ||
| 210 | if (VXFS_ISDIR(vip)) | ||
| 211 | ret |= S_IFDIR; | ||
| 212 | if (VXFS_ISBLK(vip)) | ||
| 213 | ret |= S_IFBLK; | ||
| 214 | if (VXFS_ISLNK(vip)) | ||
| 215 | ret |= S_IFLNK; | ||
| 216 | if (VXFS_ISREG(vip)) | ||
| 217 | ret |= S_IFREG; | ||
| 218 | if (VXFS_ISSOC(vip)) | ||
| 219 | ret |= S_IFSOCK; | ||
| 220 | |||
| 221 | return (ret); | ||
| 222 | } | ||
| 223 | |||
| 224 | /** | ||
| 225 | * vxfs_iinit- helper to fill inode fields | ||
| 226 | * @ip: VFS inode | ||
| 227 | * @vip: VxFS inode | ||
| 228 | * | ||
| 229 | * Description: | ||
| 230 | * vxfs_instino is a helper function to fill in all relevant | ||
| 231 | * fields in @ip from @vip. | ||
| 232 | */ | ||
| 233 | static void | ||
| 234 | vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) | ||
| 235 | { | ||
| 236 | |||
| 237 | ip->i_mode = vxfs_transmod(vip); | ||
| 238 | ip->i_uid = (uid_t)vip->vii_uid; | ||
| 239 | ip->i_gid = (gid_t)vip->vii_gid; | ||
| 240 | |||
| 241 | ip->i_nlink = vip->vii_nlink; | ||
| 242 | ip->i_size = vip->vii_size; | ||
| 243 | |||
| 244 | ip->i_atime.tv_sec = vip->vii_atime; | ||
| 245 | ip->i_ctime.tv_sec = vip->vii_ctime; | ||
| 246 | ip->i_mtime.tv_sec = vip->vii_mtime; | ||
| 247 | ip->i_atime.tv_nsec = 0; | ||
| 248 | ip->i_ctime.tv_nsec = 0; | ||
| 249 | ip->i_mtime.tv_nsec = 0; | ||
| 250 | |||
| 251 | ip->i_blksize = PAGE_SIZE; | ||
| 252 | ip->i_blocks = vip->vii_blocks; | ||
| 253 | ip->i_generation = vip->vii_gen; | ||
| 254 | |||
| 255 | ip->u.generic_ip = (void *)vip; | ||
| 256 | |||
| 257 | } | ||
| 258 | |||
| 259 | /** | ||
| 260 | * vxfs_get_fake_inode - get fake inode structure | ||
| 261 | * @sbp: filesystem superblock | ||
| 262 | * @vip: fspriv inode | ||
| 263 | * | ||
| 264 | * Description: | ||
| 265 | * vxfs_fake_inode gets a fake inode (not in the inode hash) for a | ||
| 266 | * superblock, vxfs_inode pair. | ||
| 267 | * Returns the filled VFS inode. | ||
| 268 | */ | ||
| 269 | struct inode * | ||
| 270 | vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) | ||
| 271 | { | ||
| 272 | struct inode *ip = NULL; | ||
| 273 | |||
| 274 | if ((ip = new_inode(sbp))) { | ||
| 275 | vxfs_iinit(ip, vip); | ||
| 276 | ip->i_mapping->a_ops = &vxfs_aops; | ||
| 277 | } | ||
| 278 | return (ip); | ||
| 279 | } | ||
| 280 | |||
| 281 | /** | ||
| 282 | * vxfs_put_fake_inode - free faked inode | ||
| 283 | * *ip: VFS inode | ||
| 284 | * | ||
| 285 | * Description: | ||
| 286 | * vxfs_put_fake_inode frees all data asssociated with @ip. | ||
| 287 | */ | ||
| 288 | void | ||
| 289 | vxfs_put_fake_inode(struct inode *ip) | ||
| 290 | { | ||
| 291 | iput(ip); | ||
| 292 | } | ||
| 293 | |||
| 294 | /** | ||
| 295 | * vxfs_read_inode - fill in inode information | ||
| 296 | * @ip: inode pointer to fill | ||
| 297 | * | ||
| 298 | * Description: | ||
| 299 | * vxfs_read_inode reads the disk inode for @ip and fills | ||
| 300 | * in all relevant fields in @ip. | ||
| 301 | */ | ||
| 302 | void | ||
| 303 | vxfs_read_inode(struct inode *ip) | ||
| 304 | { | ||
| 305 | struct super_block *sbp = ip->i_sb; | ||
| 306 | struct vxfs_inode_info *vip; | ||
| 307 | struct address_space_operations *aops; | ||
| 308 | ino_t ino = ip->i_ino; | ||
| 309 | |||
| 310 | if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist))) | ||
| 311 | return; | ||
| 312 | |||
| 313 | vxfs_iinit(ip, vip); | ||
| 314 | |||
| 315 | if (VXFS_ISIMMED(vip)) | ||
| 316 | aops = &vxfs_immed_aops; | ||
| 317 | else | ||
| 318 | aops = &vxfs_aops; | ||
| 319 | |||
| 320 | if (S_ISREG(ip->i_mode)) { | ||
| 321 | ip->i_fop = &vxfs_file_operations; | ||
| 322 | ip->i_mapping->a_ops = aops; | ||
| 323 | } else if (S_ISDIR(ip->i_mode)) { | ||
| 324 | ip->i_op = &vxfs_dir_inode_ops; | ||
| 325 | ip->i_fop = &vxfs_dir_operations; | ||
| 326 | ip->i_mapping->a_ops = aops; | ||
| 327 | } else if (S_ISLNK(ip->i_mode)) { | ||
| 328 | if (!VXFS_ISIMMED(vip)) { | ||
| 329 | ip->i_op = &page_symlink_inode_operations; | ||
| 330 | ip->i_mapping->a_ops = &vxfs_aops; | ||
| 331 | } else | ||
| 332 | ip->i_op = &vxfs_immed_symlink_iops; | ||
| 333 | } else | ||
| 334 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); | ||
| 335 | |||
| 336 | return; | ||
| 337 | } | ||
| 338 | |||
| 339 | /** | ||
| 340 | * vxfs_clear_inode - remove inode from main memory | ||
| 341 | * @ip: inode to discard. | ||
| 342 | * | ||
| 343 | * Description: | ||
| 344 | * vxfs_clear_inode() is called on the final iput and frees the private | ||
| 345 | * inode area. | ||
| 346 | */ | ||
| 347 | void | ||
| 348 | vxfs_clear_inode(struct inode *ip) | ||
| 349 | { | ||
| 350 | kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip); | ||
| 351 | } | ||
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h new file mode 100644 index 000000000000..240aeb11263f --- /dev/null +++ b/fs/freevxfs/vxfs_inode.h | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #ifndef _VXFS_INODE_H_ | ||
| 31 | #define _VXFS_INODE_H_ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Veritas filesystem driver - inode structure. | ||
| 35 | * | ||
| 36 | * This file contains the definition of the disk and core | ||
| 37 | * inodes of the Veritas Filesystem. | ||
| 38 | */ | ||
| 39 | |||
| 40 | |||
| 41 | #define VXFS_ISIZE 0x100 /* Inode size */ | ||
| 42 | |||
| 43 | #define VXFS_NDADDR 10 /* Number of direct addrs in inode */ | ||
| 44 | #define VXFS_NIADDR 2 /* Number of indirect addrs in inode */ | ||
| 45 | #define VXFS_NIMMED 96 /* Size of immediate data in inode */ | ||
| 46 | #define VXFS_NTYPED 6 /* Num of typed extents */ | ||
| 47 | |||
| 48 | #define VXFS_TYPED_OFFSETMASK (0x00FFFFFFFFFFFFFFULL) | ||
| 49 | #define VXFS_TYPED_TYPEMASK (0xFF00000000000000ULL) | ||
| 50 | #define VXFS_TYPED_TYPESHIFT 56 | ||
| 51 | |||
| 52 | #define VXFS_TYPED_PER_BLOCK(sbp) \ | ||
| 53 | ((sbp)->s_blocksize / sizeof(struct vxfs_typed)) | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Possible extent descriptor types for %VXFS_ORG_TYPED extents. | ||
| 57 | */ | ||
| 58 | enum { | ||
| 59 | VXFS_TYPED_INDIRECT = 1, | ||
| 60 | VXFS_TYPED_DATA = 2, | ||
| 61 | VXFS_TYPED_INDIRECT_DEV4 = 3, | ||
| 62 | VXFS_TYPED_DATA_DEV4 = 4, | ||
| 63 | }; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Data stored immediately in the inode. | ||
| 67 | */ | ||
| 68 | struct vxfs_immed { | ||
| 69 | u_int8_t vi_immed[VXFS_NIMMED]; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct vxfs_ext4 { | ||
| 73 | u_int32_t ve4_spare; /* ?? */ | ||
| 74 | u_int32_t ve4_indsize; /* Indirect extent size */ | ||
| 75 | vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ | ||
| 76 | struct direct { /* Direct extents */ | ||
| 77 | vx_daddr_t extent; /* Extent number */ | ||
| 78 | int32_t size; /* Size of extent */ | ||
| 79 | } ve4_direct[VXFS_NDADDR]; | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct vxfs_typed { | ||
| 83 | u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ | ||
| 84 | vx_daddr_t vt_block; /* Extent block */ | ||
| 85 | int32_t vt_size; /* Size in blocks */ | ||
| 86 | }; | ||
| 87 | |||
| 88 | struct vxfs_typed_dev4 { | ||
| 89 | u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ | ||
| 90 | u_int64_t vd4_block; /* Extent block */ | ||
| 91 | u_int64_t vd4_size; /* Size in blocks */ | ||
| 92 | int32_t vd4_dev; /* Device ID */ | ||
| 93 | u_int32_t __pad1; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * The inode as contained on the physical device. | ||
| 98 | */ | ||
| 99 | struct vxfs_dinode { | ||
| 100 | int32_t vdi_mode; | ||
| 101 | u_int32_t vdi_nlink; /* Link count */ | ||
| 102 | u_int32_t vdi_uid; /* UID */ | ||
| 103 | u_int32_t vdi_gid; /* GID */ | ||
| 104 | u_int64_t vdi_size; /* Inode size in bytes */ | ||
| 105 | u_int32_t vdi_atime; /* Last time accessed - sec */ | ||
| 106 | u_int32_t vdi_autime; /* Last time accessed - usec */ | ||
| 107 | u_int32_t vdi_mtime; /* Last modify time - sec */ | ||
| 108 | u_int32_t vdi_mutime; /* Last modify time - usec */ | ||
| 109 | u_int32_t vdi_ctime; /* Create time - sec */ | ||
| 110 | u_int32_t vdi_cutime; /* Create time - usec */ | ||
| 111 | u_int8_t vdi_aflags; /* Allocation flags */ | ||
| 112 | u_int8_t vdi_orgtype; /* Organisation type */ | ||
| 113 | u_int16_t vdi_eopflags; | ||
| 114 | u_int32_t vdi_eopdata; | ||
| 115 | union { | ||
| 116 | u_int32_t rdev; | ||
| 117 | u_int32_t dotdot; | ||
| 118 | struct { | ||
| 119 | u_int32_t reserved; | ||
| 120 | u_int32_t fixextsize; | ||
| 121 | } i_regular; | ||
| 122 | struct { | ||
| 123 | u_int32_t matchino; | ||
| 124 | u_int32_t fsetindex; | ||
| 125 | } i_vxspec; | ||
| 126 | u_int64_t align; | ||
| 127 | } vdi_ftarea; | ||
| 128 | u_int32_t vdi_blocks; /* How much blocks does inode occupy */ | ||
| 129 | u_int32_t vdi_gen; /* Inode generation */ | ||
| 130 | u_int64_t vdi_version; /* Version */ | ||
| 131 | union { | ||
| 132 | struct vxfs_immed immed; | ||
| 133 | struct vxfs_ext4 ext4; | ||
| 134 | struct vxfs_typed typed[VXFS_NTYPED]; | ||
| 135 | } vdi_org; | ||
| 136 | u_int32_t vdi_iattrino; | ||
| 137 | }; | ||
| 138 | |||
| 139 | #define vdi_rdev vdi_ftarea.rdev | ||
| 140 | #define vdi_dotdot vdi_ftarea.dotdot | ||
| 141 | #define vdi_fixextsize vdi_ftarea.regular.fixextsize | ||
| 142 | #define vdi_matchino vdi_ftarea.vxspec.matchino | ||
| 143 | #define vdi_fsetindex vdi_ftarea.vxspec.fsetindex | ||
| 144 | |||
| 145 | #define vdi_immed vdi_org.immed | ||
| 146 | #define vdi_ext4 vdi_org.ext4 | ||
| 147 | #define vdi_typed vdi_org.typed | ||
| 148 | |||
| 149 | |||
| 150 | /* | ||
| 151 | * The inode as represented in the main memory. | ||
| 152 | * | ||
| 153 | * TBD: This should become a separate structure... | ||
| 154 | */ | ||
| 155 | #define vxfs_inode_info vxfs_dinode | ||
| 156 | |||
| 157 | #define vii_mode vdi_mode | ||
| 158 | #define vii_uid vdi_uid | ||
| 159 | #define vii_gid vdi_gid | ||
| 160 | #define vii_nlink vdi_nlink | ||
| 161 | #define vii_size vdi_size | ||
| 162 | #define vii_atime vdi_atime | ||
| 163 | #define vii_ctime vdi_ctime | ||
| 164 | #define vii_mtime vdi_mtime | ||
| 165 | #define vii_blocks vdi_blocks | ||
| 166 | #define vii_org vdi_org | ||
| 167 | #define vii_orgtype vdi_orgtype | ||
| 168 | #define vii_gen vdi_gen | ||
| 169 | |||
| 170 | #define vii_rdev vdi_ftarea.rdev | ||
| 171 | #define vii_dotdot vdi_ftarea.dotdot | ||
| 172 | #define vii_fixextsize vdi_ftarea.regular.fixextsize | ||
| 173 | #define vii_matchino vdi_ftarea.vxspec.matchino | ||
| 174 | #define vii_fsetindex vdi_ftarea.vxspec.fsetindex | ||
| 175 | |||
| 176 | #define vii_immed vdi_org.immed | ||
| 177 | #define vii_ext4 vdi_org.ext4 | ||
| 178 | #define vii_typed vdi_org.typed | ||
| 179 | |||
| 180 | #endif /* _VXFS_INODE_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_kcompat.h b/fs/freevxfs/vxfs_kcompat.h new file mode 100644 index 000000000000..342a4cc860f4 --- /dev/null +++ b/fs/freevxfs/vxfs_kcompat.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #ifndef _VXFS_KCOMPAT_H | ||
| 2 | #define _VXFS_KCOMPAT_H | ||
| 3 | |||
| 4 | #include <linux/version.h> | ||
| 5 | |||
| 6 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | ||
| 7 | |||
| 8 | #include <linux/blkdev.h> | ||
| 9 | |||
| 10 | typedef long sector_t; | ||
| 11 | |||
| 12 | /* From include/linux/fs.h (Linux 2.5.2-pre3) */ | ||
| 13 | static inline struct buffer_head * sb_bread(struct super_block *sb, int block) | ||
| 14 | { | ||
| 15 | return bread(sb->s_dev, block, sb->s_blocksize); | ||
| 16 | } | ||
| 17 | |||
| 18 | /* Dito. */ | ||
| 19 | static inline void map_bh(struct buffer_head *bh, struct super_block *sb, int block) | ||
| 20 | { | ||
| 21 | bh->b_state |= 1 << BH_Mapped; | ||
| 22 | bh->b_dev = sb->s_dev; | ||
| 23 | bh->b_blocknr = block; | ||
| 24 | } | ||
| 25 | |||
| 26 | /* From fs/block_dev.c (Linux 2.5.2-pre2) */ | ||
| 27 | static inline int sb_set_blocksize(struct super_block *sb, int size) | ||
| 28 | { | ||
| 29 | int bits; | ||
| 30 | if (set_blocksize(sb->s_dev, size) < 0) | ||
| 31 | return 0; | ||
| 32 | sb->s_blocksize = size; | ||
| 33 | for (bits = 9, size >>= 9; size >>= 1; bits++) | ||
| 34 | ; | ||
| 35 | sb->s_blocksize_bits = bits; | ||
| 36 | return sb->s_blocksize; | ||
| 37 | } | ||
| 38 | |||
| 39 | /* Dito. */ | ||
| 40 | static inline int sb_min_blocksize(struct super_block *sb, int size) | ||
| 41 | { | ||
| 42 | int minsize = get_hardsect_size(sb->s_dev); | ||
| 43 | if (size < minsize) | ||
| 44 | size = minsize; | ||
| 45 | return sb_set_blocksize(sb, size); | ||
| 46 | } | ||
| 47 | |||
| 48 | #endif /* Kernel 2.4 */ | ||
| 49 | #endif /* _VXFS_KCOMPAT_H */ | ||
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c new file mode 100644 index 000000000000..506ae251d2c0 --- /dev/null +++ b/fs/freevxfs/vxfs_lookup.c | |||
| @@ -0,0 +1,328 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - lookup and other directory related code. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/time.h> | ||
| 35 | #include <linux/mm.h> | ||
| 36 | #include <linux/highmem.h> | ||
| 37 | #include <linux/kernel.h> | ||
| 38 | #include <linux/pagemap.h> | ||
| 39 | #include <linux/smp_lock.h> | ||
| 40 | |||
| 41 | #include "vxfs.h" | ||
| 42 | #include "vxfs_dir.h" | ||
| 43 | #include "vxfs_inode.h" | ||
| 44 | #include "vxfs_extern.h" | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Number of VxFS blocks per page. | ||
| 48 | */ | ||
| 49 | #define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize)) | ||
| 50 | |||
| 51 | |||
| 52 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); | ||
| 53 | static int vxfs_readdir(struct file *, void *, filldir_t); | ||
| 54 | |||
| 55 | struct inode_operations vxfs_dir_inode_ops = { | ||
| 56 | .lookup = vxfs_lookup, | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct file_operations vxfs_dir_operations = { | ||
| 60 | .readdir = vxfs_readdir, | ||
| 61 | }; | ||
| 62 | |||
| 63 | |||
| 64 | static __inline__ u_long | ||
| 65 | dir_pages(struct inode *inode) | ||
| 66 | { | ||
| 67 | return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
| 68 | } | ||
| 69 | |||
| 70 | static __inline__ u_long | ||
| 71 | dir_blocks(struct inode *ip) | ||
| 72 | { | ||
| 73 | u_long bsize = ip->i_sb->s_blocksize; | ||
| 74 | return (ip->i_size + bsize - 1) & ~(bsize - 1); | ||
| 75 | } | ||
| 76 | |||
| 77 | /* | ||
| 78 | * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure. | ||
| 79 | * | ||
| 80 | * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller. | ||
| 81 | */ | ||
| 82 | static __inline__ int | ||
| 83 | vxfs_match(int len, const char * const name, struct vxfs_direct *de) | ||
| 84 | { | ||
| 85 | if (len != de->d_namelen) | ||
| 86 | return 0; | ||
| 87 | if (!de->d_ino) | ||
| 88 | return 0; | ||
| 89 | return !memcmp(name, de->d_name, len); | ||
| 90 | } | ||
| 91 | |||
| 92 | static __inline__ struct vxfs_direct * | ||
| 93 | vxfs_next_entry(struct vxfs_direct *de) | ||
| 94 | { | ||
| 95 | return ((struct vxfs_direct *)((char*)de + de->d_reclen)); | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * vxfs_find_entry - find a mathing directory entry for a dentry | ||
| 100 | * @ip: directory inode | ||
| 101 | * @dp: dentry for which we want to find a direct | ||
| 102 | * @ppp: gets filled with the page the return value sits in | ||
| 103 | * | ||
| 104 | * Description: | ||
| 105 | * vxfs_find_entry finds a &struct vxfs_direct for the VFS directory | ||
| 106 | * cache entry @dp. @ppp will be filled with the page the return | ||
| 107 | * value resides in. | ||
| 108 | * | ||
| 109 | * Returns: | ||
| 110 | * The wanted direct on success, else a NULL pointer. | ||
| 111 | */ | ||
| 112 | static struct vxfs_direct * | ||
| 113 | vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) | ||
| 114 | { | ||
| 115 | u_long npages, page, nblocks, pblocks, block; | ||
| 116 | u_long bsize = ip->i_sb->s_blocksize; | ||
| 117 | const char *name = dp->d_name.name; | ||
| 118 | int namelen = dp->d_name.len; | ||
| 119 | |||
| 120 | npages = dir_pages(ip); | ||
| 121 | nblocks = dir_blocks(ip); | ||
| 122 | pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb); | ||
| 123 | |||
| 124 | for (page = 0; page < npages; page++) { | ||
| 125 | caddr_t kaddr; | ||
| 126 | struct page *pp; | ||
| 127 | |||
| 128 | pp = vxfs_get_page(ip->i_mapping, page); | ||
| 129 | if (IS_ERR(pp)) | ||
| 130 | continue; | ||
| 131 | kaddr = (caddr_t)page_address(pp); | ||
| 132 | |||
| 133 | for (block = 0; block <= nblocks && block <= pblocks; block++) { | ||
| 134 | caddr_t baddr, limit; | ||
| 135 | struct vxfs_dirblk *dbp; | ||
| 136 | struct vxfs_direct *de; | ||
| 137 | |||
| 138 | baddr = kaddr + (block * bsize); | ||
| 139 | limit = baddr + bsize - VXFS_DIRLEN(1); | ||
| 140 | |||
| 141 | dbp = (struct vxfs_dirblk *)baddr; | ||
| 142 | de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp)); | ||
| 143 | |||
| 144 | for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { | ||
| 145 | if (!de->d_reclen) | ||
| 146 | break; | ||
| 147 | if (!de->d_ino) | ||
| 148 | continue; | ||
| 149 | if (vxfs_match(namelen, name, de)) { | ||
| 150 | *ppp = pp; | ||
| 151 | return (de); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | } | ||
| 155 | vxfs_put_page(pp); | ||
| 156 | } | ||
| 157 | |||
| 158 | return NULL; | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * vxfs_inode_by_name - find inode number for dentry | ||
| 163 | * @dip: directory to search in | ||
| 164 | * @dp: dentry we seach for | ||
| 165 | * | ||
| 166 | * Description: | ||
| 167 | * vxfs_inode_by_name finds out the inode number of | ||
| 168 | * the path component described by @dp in @dip. | ||
| 169 | * | ||
| 170 | * Returns: | ||
| 171 | * The wanted inode number on success, else Zero. | ||
| 172 | */ | ||
| 173 | static ino_t | ||
| 174 | vxfs_inode_by_name(struct inode *dip, struct dentry *dp) | ||
| 175 | { | ||
| 176 | struct vxfs_direct *de; | ||
| 177 | struct page *pp; | ||
| 178 | ino_t ino = 0; | ||
| 179 | |||
| 180 | de = vxfs_find_entry(dip, dp, &pp); | ||
| 181 | if (de) { | ||
| 182 | ino = de->d_ino; | ||
| 183 | kunmap(pp); | ||
| 184 | page_cache_release(pp); | ||
| 185 | } | ||
| 186 | |||
| 187 | return (ino); | ||
| 188 | } | ||
| 189 | |||
| 190 | /** | ||
| 191 | * vxfs_lookup - lookup pathname component | ||
| 192 | * @dip: dir in which we lookup | ||
| 193 | * @dp: dentry we lookup | ||
| 194 | * @nd: lookup nameidata | ||
| 195 | * | ||
| 196 | * Description: | ||
| 197 | * vxfs_lookup tries to lookup the pathname component described | ||
| 198 | * by @dp in @dip. | ||
| 199 | * | ||
| 200 | * Returns: | ||
| 201 | * A NULL-pointer on success, else an negative error code encoded | ||
| 202 | * in the return pointer. | ||
| 203 | */ | ||
| 204 | static struct dentry * | ||
| 205 | vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) | ||
| 206 | { | ||
| 207 | struct inode *ip = NULL; | ||
| 208 | ino_t ino; | ||
| 209 | |||
| 210 | if (dp->d_name.len > VXFS_NAMELEN) | ||
| 211 | return ERR_PTR(-ENAMETOOLONG); | ||
| 212 | |||
| 213 | lock_kernel(); | ||
| 214 | ino = vxfs_inode_by_name(dip, dp); | ||
| 215 | if (ino) { | ||
| 216 | ip = iget(dip->i_sb, ino); | ||
| 217 | if (!ip) { | ||
| 218 | unlock_kernel(); | ||
| 219 | return ERR_PTR(-EACCES); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | unlock_kernel(); | ||
| 223 | d_add(dp, ip); | ||
| 224 | return NULL; | ||
| 225 | } | ||
| 226 | |||
| 227 | /** | ||
| 228 | * vxfs_readdir - read a directory | ||
| 229 | * @fp: the directory to read | ||
| 230 | * @retp: return buffer | ||
| 231 | * @filler: filldir callback | ||
| 232 | * | ||
| 233 | * Description: | ||
| 234 | * vxfs_readdir fills @retp with directory entries from @fp | ||
| 235 | * using the VFS supplied callback @filler. | ||
| 236 | * | ||
| 237 | * Returns: | ||
| 238 | * Zero. | ||
| 239 | */ | ||
| 240 | static int | ||
| 241 | vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | ||
| 242 | { | ||
| 243 | struct inode *ip = fp->f_dentry->d_inode; | ||
| 244 | struct super_block *sbp = ip->i_sb; | ||
| 245 | u_long bsize = sbp->s_blocksize; | ||
| 246 | u_long page, npages, block, pblocks, nblocks, offset; | ||
| 247 | loff_t pos; | ||
| 248 | |||
| 249 | switch ((long)fp->f_pos) { | ||
| 250 | case 0: | ||
| 251 | if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0) | ||
| 252 | goto out; | ||
| 253 | fp->f_pos++; | ||
| 254 | /* fallthrough */ | ||
| 255 | case 1: | ||
| 256 | if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0) | ||
| 257 | goto out; | ||
| 258 | fp->f_pos++; | ||
| 259 | /* fallthrough */ | ||
| 260 | } | ||
| 261 | |||
| 262 | pos = fp->f_pos - 2; | ||
| 263 | |||
| 264 | if (pos > VXFS_DIRROUND(ip->i_size)) { | ||
| 265 | unlock_kernel(); | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | npages = dir_pages(ip); | ||
| 270 | nblocks = dir_blocks(ip); | ||
| 271 | pblocks = VXFS_BLOCK_PER_PAGE(sbp); | ||
| 272 | |||
| 273 | page = pos >> PAGE_CACHE_SHIFT; | ||
| 274 | offset = pos & ~PAGE_CACHE_MASK; | ||
| 275 | block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; | ||
| 276 | |||
| 277 | for (; page < npages; page++, block = 0) { | ||
| 278 | caddr_t kaddr; | ||
| 279 | struct page *pp; | ||
| 280 | |||
| 281 | pp = vxfs_get_page(ip->i_mapping, page); | ||
| 282 | if (IS_ERR(pp)) | ||
| 283 | continue; | ||
| 284 | kaddr = (caddr_t)page_address(pp); | ||
| 285 | |||
| 286 | for (; block <= nblocks && block <= pblocks; block++) { | ||
| 287 | caddr_t baddr, limit; | ||
| 288 | struct vxfs_dirblk *dbp; | ||
| 289 | struct vxfs_direct *de; | ||
| 290 | |||
| 291 | baddr = kaddr + (block * bsize); | ||
| 292 | limit = baddr + bsize - VXFS_DIRLEN(1); | ||
| 293 | |||
| 294 | dbp = (struct vxfs_dirblk *)baddr; | ||
| 295 | de = (struct vxfs_direct *) | ||
| 296 | (offset ? | ||
| 297 | (kaddr + offset) : | ||
| 298 | (baddr + VXFS_DIRBLKOV(dbp))); | ||
| 299 | |||
| 300 | for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { | ||
| 301 | int over; | ||
| 302 | |||
| 303 | if (!de->d_reclen) | ||
| 304 | break; | ||
| 305 | if (!de->d_ino) | ||
| 306 | continue; | ||
| 307 | |||
| 308 | offset = (caddr_t)de - kaddr; | ||
| 309 | over = filler(retp, de->d_name, de->d_namelen, | ||
| 310 | ((page << PAGE_CACHE_SHIFT) | offset) + 2, | ||
| 311 | de->d_ino, DT_UNKNOWN); | ||
| 312 | if (over) { | ||
| 313 | vxfs_put_page(pp); | ||
| 314 | goto done; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | offset = 0; | ||
| 318 | } | ||
| 319 | vxfs_put_page(pp); | ||
| 320 | offset = 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | done: | ||
| 324 | fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; | ||
| 325 | out: | ||
| 326 | unlock_kernel(); | ||
| 327 | return 0; | ||
| 328 | } | ||
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c new file mode 100644 index 000000000000..7a204e31aad9 --- /dev/null +++ b/fs/freevxfs/vxfs_olt.c | |||
| @@ -0,0 +1,132 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - object location table support. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/buffer_head.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | |||
| 37 | #include "vxfs.h" | ||
| 38 | #include "vxfs_olt.h" | ||
| 39 | |||
| 40 | |||
| 41 | static __inline__ void | ||
| 42 | vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) | ||
| 43 | { | ||
| 44 | if (infp->vsi_fshino) | ||
| 45 | BUG(); | ||
| 46 | infp->vsi_fshino = fshp->olt_fsino[0]; | ||
| 47 | } | ||
| 48 | |||
| 49 | static __inline__ void | ||
| 50 | vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) | ||
| 51 | { | ||
| 52 | if (infp->vsi_iext) | ||
| 53 | BUG(); | ||
| 54 | infp->vsi_iext = ilistp->olt_iext[0]; | ||
| 55 | } | ||
| 56 | |||
| 57 | static __inline__ u_long | ||
| 58 | vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize) | ||
| 59 | { | ||
| 60 | if (sbp->s_blocksize % bsize) | ||
| 61 | BUG(); | ||
| 62 | return (block * (sbp->s_blocksize / bsize)); | ||
| 63 | } | ||
| 64 | |||
| 65 | |||
| 66 | /** | ||
| 67 | * vxfs_read_olt - read olt | ||
| 68 | * @sbp: superblock of the filesystem | ||
| 69 | * @bsize: blocksize of the filesystem | ||
| 70 | * | ||
| 71 | * Description: | ||
| 72 | * vxfs_read_olt reads the olt of the filesystem described by @sbp | ||
| 73 | * into main memory and does some basic setup. | ||
| 74 | * | ||
| 75 | * Returns: | ||
| 76 | * Zero on success, else a negative error code. | ||
| 77 | */ | ||
| 78 | int | ||
| 79 | vxfs_read_olt(struct super_block *sbp, u_long bsize) | ||
| 80 | { | ||
| 81 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
| 82 | struct buffer_head *bp; | ||
| 83 | struct vxfs_olt *op; | ||
| 84 | char *oaddr, *eaddr; | ||
| 85 | |||
| 86 | |||
| 87 | bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize)); | ||
| 88 | if (!bp || !bp->b_data) | ||
| 89 | goto fail; | ||
| 90 | |||
| 91 | op = (struct vxfs_olt *)bp->b_data; | ||
| 92 | if (op->olt_magic != VXFS_OLT_MAGIC) { | ||
| 93 | printk(KERN_NOTICE "vxfs: ivalid olt magic number\n"); | ||
| 94 | goto fail; | ||
| 95 | } | ||
| 96 | |||
| 97 | /* | ||
| 98 | * It is in theory possible that vsi_oltsize is > 1. | ||
| 99 | * I've not seen any such filesystem yet and I'm lazy.. --hch | ||
| 100 | */ | ||
| 101 | if (infp->vsi_oltsize > 1) { | ||
| 102 | printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n"); | ||
| 103 | printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n"); | ||
| 104 | goto fail; | ||
| 105 | } | ||
| 106 | |||
| 107 | oaddr = (char *)bp->b_data + op->olt_size; | ||
| 108 | eaddr = (char *)bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize); | ||
| 109 | |||
| 110 | while (oaddr < eaddr) { | ||
| 111 | struct vxfs_oltcommon *ocp = | ||
| 112 | (struct vxfs_oltcommon *)oaddr; | ||
| 113 | |||
| 114 | switch (ocp->olt_type) { | ||
| 115 | case VXFS_OLT_FSHEAD: | ||
| 116 | vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp); | ||
| 117 | break; | ||
| 118 | case VXFS_OLT_ILIST: | ||
| 119 | vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp); | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | |||
| 123 | oaddr += ocp->olt_size; | ||
| 124 | } | ||
| 125 | |||
| 126 | brelse(bp); | ||
| 127 | return 0; | ||
| 128 | |||
| 129 | fail: | ||
| 130 | brelse(bp); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h new file mode 100644 index 000000000000..d8324296486f --- /dev/null +++ b/fs/freevxfs/vxfs_olt.h | |||
| @@ -0,0 +1,145 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #ifndef _VXFS_OLT_H_ | ||
| 31 | #define _VXFS_OLT_H_ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Veritas filesystem driver - Object Location Table data structures. | ||
| 35 | * | ||
| 36 | * This file contains definitions for the Object Location Table used | ||
| 37 | * by the Veritas Filesystem version 2 and newer. | ||
| 38 | */ | ||
| 39 | |||
| 40 | |||
| 41 | /* | ||
| 42 | * OLT magic number (vxfs_olt->olt_magic). | ||
| 43 | */ | ||
| 44 | #define VXFS_OLT_MAGIC 0xa504FCF5 | ||
| 45 | |||
| 46 | /* | ||
| 47 | * VxFS OLT entry types. | ||
| 48 | */ | ||
| 49 | enum { | ||
| 50 | VXFS_OLT_FREE = 1, | ||
| 51 | VXFS_OLT_FSHEAD = 2, | ||
| 52 | VXFS_OLT_CUT = 3, | ||
| 53 | VXFS_OLT_ILIST = 4, | ||
| 54 | VXFS_OLT_DEV = 5, | ||
| 55 | VXFS_OLT_SB = 6 | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* | ||
| 59 | * VxFS OLT header. | ||
| 60 | * | ||
| 61 | * The Object Location Table header is placed at the beginning of each | ||
| 62 | * OLT extent. It is used to fing certain filesystem-wide metadata, e.g. | ||
| 63 | * the inital inode list, the fileset header or the device configuration. | ||
| 64 | */ | ||
| 65 | struct vxfs_olt { | ||
| 66 | u_int32_t olt_magic; /* magic number */ | ||
| 67 | u_int32_t olt_size; /* size of this entry */ | ||
| 68 | u_int32_t olt_checksum; /* checksum of extent */ | ||
| 69 | u_int32_t __unused1; /* ??? */ | ||
| 70 | u_int32_t olt_mtime; /* time of last mod. (sec) */ | ||
| 71 | u_int32_t olt_mutime; /* time of last mod. (usec) */ | ||
| 72 | u_int32_t olt_totfree; /* free space in OLT extent */ | ||
| 73 | vx_daddr_t olt_extents[2]; /* addr of this extent, replica */ | ||
| 74 | u_int32_t olt_esize; /* size of this extent */ | ||
| 75 | vx_daddr_t olt_next[2]; /* addr of next extent, replica */ | ||
| 76 | u_int32_t olt_nsize; /* size of next extent */ | ||
| 77 | u_int32_t __unused2; /* align to 8 byte boundary */ | ||
| 78 | }; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * VxFS common OLT entry (on disk). | ||
| 82 | */ | ||
| 83 | struct vxfs_oltcommon { | ||
| 84 | u_int32_t olt_type; /* type of this record */ | ||
| 85 | u_int32_t olt_size; /* size of this record */ | ||
| 86 | }; | ||
| 87 | |||
| 88 | /* | ||
| 89 | * VxFS free OLT entry (on disk). | ||
| 90 | */ | ||
| 91 | struct vxfs_oltfree { | ||
| 92 | u_int32_t olt_type; /* type of this record */ | ||
| 93 | u_int32_t olt_fsize; /* size of this free record */ | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * VxFS initial-inode list (on disk). | ||
| 98 | */ | ||
| 99 | struct vxfs_oltilist { | ||
| 100 | u_int32_t olt_type; /* type of this record */ | ||
| 101 | u_int32_t olt_size; /* size of this record */ | ||
| 102 | vx_ino_t olt_iext[2]; /* initial inode list, replica */ | ||
| 103 | }; | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Current Usage Table | ||
| 107 | */ | ||
| 108 | struct vxfs_oltcut { | ||
| 109 | u_int32_t olt_type; /* type of this record */ | ||
| 110 | u_int32_t olt_size; /* size of this record */ | ||
| 111 | vx_ino_t olt_cutino; /* inode of current usage table */ | ||
| 112 | u_int32_t __pad; /* unused, 8 byte align */ | ||
| 113 | }; | ||
| 114 | |||
| 115 | /* | ||
| 116 | * Inodes containing Superblock, Intent log and OLTs | ||
| 117 | */ | ||
| 118 | struct vxfs_oltsb { | ||
| 119 | u_int32_t olt_type; /* type of this record */ | ||
| 120 | u_int32_t olt_size; /* size of this record */ | ||
| 121 | vx_ino_t olt_sbino; /* inode of superblock file */ | ||
| 122 | u_int32_t __unused1; /* ??? */ | ||
| 123 | vx_ino_t olt_logino[2]; /* inode of log file,replica */ | ||
| 124 | vx_ino_t olt_oltino[2]; /* inode of OLT, replica */ | ||
| 125 | }; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Inode containing device configuration + it's replica | ||
| 129 | */ | ||
| 130 | struct vxfs_oltdev { | ||
| 131 | u_int32_t olt_type; /* type of this record */ | ||
| 132 | u_int32_t olt_size; /* size of this record */ | ||
| 133 | vx_ino_t olt_devino[2]; /* inode of device config files */ | ||
| 134 | }; | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Fileset header | ||
| 138 | */ | ||
| 139 | struct vxfs_oltfshead { | ||
| 140 | u_int32_t olt_type; /* type number */ | ||
| 141 | u_int32_t olt_size; /* size of this record */ | ||
| 142 | vx_ino_t olt_fsino[2]; /* inodes of fileset header */ | ||
| 143 | }; | ||
| 144 | |||
| 145 | #endif /* _VXFS_OLT_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c new file mode 100644 index 000000000000..5e305612054a --- /dev/null +++ b/fs/freevxfs/vxfs_subr.c | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - shared subroutines. | ||
| 32 | */ | ||
| 33 | #include <linux/fs.h> | ||
| 34 | #include <linux/buffer_head.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/pagemap.h> | ||
| 38 | |||
| 39 | #include "vxfs_kcompat.h" | ||
| 40 | #include "vxfs_extern.h" | ||
| 41 | |||
| 42 | |||
| 43 | static int vxfs_readpage(struct file *, struct page *); | ||
| 44 | static sector_t vxfs_bmap(struct address_space *, sector_t); | ||
| 45 | |||
| 46 | struct address_space_operations vxfs_aops = { | ||
| 47 | .readpage = vxfs_readpage, | ||
| 48 | .bmap = vxfs_bmap, | ||
| 49 | .sync_page = block_sync_page, | ||
| 50 | }; | ||
| 51 | |||
| 52 | inline void | ||
| 53 | vxfs_put_page(struct page *pp) | ||
| 54 | { | ||
| 55 | kunmap(pp); | ||
| 56 | page_cache_release(pp); | ||
| 57 | } | ||
| 58 | |||
| 59 | /** | ||
| 60 | * vxfs_get_page - read a page into memory. | ||
| 61 | * @ip: inode to read from | ||
| 62 | * @n: page number | ||
| 63 | * | ||
| 64 | * Description: | ||
| 65 | * vxfs_get_page reads the @n th page of @ip into the pagecache. | ||
| 66 | * | ||
| 67 | * Returns: | ||
| 68 | * The wanted page on success, else a NULL pointer. | ||
| 69 | */ | ||
| 70 | struct page * | ||
| 71 | vxfs_get_page(struct address_space *mapping, u_long n) | ||
| 72 | { | ||
| 73 | struct page * pp; | ||
| 74 | |||
| 75 | pp = read_cache_page(mapping, n, | ||
| 76 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
| 77 | |||
| 78 | if (!IS_ERR(pp)) { | ||
| 79 | wait_on_page_locked(pp); | ||
| 80 | kmap(pp); | ||
| 81 | if (!PageUptodate(pp)) | ||
| 82 | goto fail; | ||
| 83 | /** if (!PageChecked(pp)) **/ | ||
| 84 | /** vxfs_check_page(pp); **/ | ||
| 85 | if (PageError(pp)) | ||
| 86 | goto fail; | ||
| 87 | } | ||
| 88 | |||
| 89 | return (pp); | ||
| 90 | |||
| 91 | fail: | ||
| 92 | vxfs_put_page(pp); | ||
| 93 | return ERR_PTR(-EIO); | ||
| 94 | } | ||
| 95 | |||
| 96 | /** | ||
| 97 | * vxfs_bread - read buffer for a give inode,block tuple | ||
| 98 | * @ip: inode | ||
| 99 | * @block: logical block | ||
| 100 | * | ||
| 101 | * Description: | ||
| 102 | * The vxfs_bread function reads block no @block of | ||
| 103 | * @ip into the buffercache. | ||
| 104 | * | ||
| 105 | * Returns: | ||
| 106 | * The resulting &struct buffer_head. | ||
| 107 | */ | ||
| 108 | struct buffer_head * | ||
| 109 | vxfs_bread(struct inode *ip, int block) | ||
| 110 | { | ||
| 111 | struct buffer_head *bp; | ||
| 112 | daddr_t pblock; | ||
| 113 | |||
| 114 | pblock = vxfs_bmap1(ip, block); | ||
| 115 | bp = sb_bread(ip->i_sb, pblock); | ||
| 116 | |||
| 117 | return (bp); | ||
| 118 | } | ||
| 119 | |||
| 120 | /** | ||
| 121 | * vxfs_get_block - locate buffer for given inode,block tuple | ||
| 122 | * @ip: inode | ||
| 123 | * @iblock: logical block | ||
| 124 | * @bp: buffer skeleton | ||
| 125 | * @create: %TRUE if blocks may be newly allocated. | ||
| 126 | * | ||
| 127 | * Description: | ||
| 128 | * The vxfs_get_block function fills @bp with the right physical | ||
| 129 | * block and device number to perform a lowlevel read/write on | ||
| 130 | * it. | ||
| 131 | * | ||
| 132 | * Returns: | ||
| 133 | * Zero on success, else a negativ error code (-EIO). | ||
| 134 | */ | ||
| 135 | static int | ||
| 136 | vxfs_getblk(struct inode *ip, sector_t iblock, | ||
| 137 | struct buffer_head *bp, int create) | ||
| 138 | { | ||
| 139 | daddr_t pblock; | ||
| 140 | |||
| 141 | pblock = vxfs_bmap1(ip, iblock); | ||
| 142 | if (pblock != 0) { | ||
| 143 | map_bh(bp, ip->i_sb, pblock); | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | |||
| 147 | return -EIO; | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * vxfs_readpage - read one page synchronously into the pagecache | ||
| 152 | * @file: file context (unused) | ||
| 153 | * @page: page frame to fill in. | ||
| 154 | * | ||
| 155 | * Description: | ||
| 156 | * The vxfs_readpage routine reads @page synchronously into the | ||
| 157 | * pagecache. | ||
| 158 | * | ||
| 159 | * Returns: | ||
| 160 | * Zero on success, else a negative error code. | ||
| 161 | * | ||
| 162 | * Locking status: | ||
| 163 | * @page is locked and will be unlocked. | ||
| 164 | */ | ||
| 165 | static int | ||
| 166 | vxfs_readpage(struct file *file, struct page *page) | ||
| 167 | { | ||
| 168 | return block_read_full_page(page, vxfs_getblk); | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 172 | * vxfs_bmap - perform logical to physical block mapping | ||
| 173 | * @mapping: logical to physical mapping to use | ||
| 174 | * @block: logical block (relative to @mapping). | ||
| 175 | * | ||
| 176 | * Description: | ||
| 177 | * Vxfs_bmap find out the corresponding phsical block to the | ||
| 178 | * @mapping, @block pair. | ||
| 179 | * | ||
| 180 | * Returns: | ||
| 181 | * Physical block number on success, else Zero. | ||
| 182 | * | ||
| 183 | * Locking status: | ||
| 184 | * We are under the bkl. | ||
| 185 | */ | ||
| 186 | static sector_t | ||
| 187 | vxfs_bmap(struct address_space *mapping, sector_t block) | ||
| 188 | { | ||
| 189 | return generic_block_bmap(mapping, block, vxfs_getblk); | ||
| 190 | } | ||
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c new file mode 100644 index 000000000000..0ae2c7b8182a --- /dev/null +++ b/fs/freevxfs/vxfs_super.c | |||
| @@ -0,0 +1,278 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. The name of the author may not be used to endorse or promote products | ||
| 12 | * derived from this software without specific prior written permission. | ||
| 13 | * | ||
| 14 | * Alternatively, this software may be distributed under the terms of the | ||
| 15 | * GNU General Public License ("GPL"). | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 27 | * SUCH DAMAGE. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Veritas filesystem driver - superblock related routines. | ||
| 32 | */ | ||
| 33 | #include <linux/init.h> | ||
| 34 | #include <linux/module.h> | ||
| 35 | |||
| 36 | #include <linux/blkdev.h> | ||
| 37 | #include <linux/fs.h> | ||
| 38 | #include <linux/buffer_head.h> | ||
| 39 | #include <linux/kernel.h> | ||
| 40 | #include <linux/slab.h> | ||
| 41 | #include <linux/stat.h> | ||
| 42 | #include <linux/vfs.h> | ||
| 43 | |||
| 44 | #include "vxfs.h" | ||
| 45 | #include "vxfs_extern.h" | ||
| 46 | #include "vxfs_dir.h" | ||
| 47 | #include "vxfs_inode.h" | ||
| 48 | |||
| 49 | |||
| 50 | MODULE_AUTHOR("Christoph Hellwig"); | ||
| 51 | MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); | ||
| 52 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 53 | |||
| 54 | MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */ | ||
| 55 | |||
| 56 | |||
| 57 | static void vxfs_put_super(struct super_block *); | ||
| 58 | static int vxfs_statfs(struct super_block *, struct kstatfs *); | ||
| 59 | static int vxfs_remount(struct super_block *, int *, char *); | ||
| 60 | |||
| 61 | static struct super_operations vxfs_super_ops = { | ||
| 62 | .read_inode = vxfs_read_inode, | ||
| 63 | .clear_inode = vxfs_clear_inode, | ||
| 64 | .put_super = vxfs_put_super, | ||
| 65 | .statfs = vxfs_statfs, | ||
| 66 | .remount_fs = vxfs_remount, | ||
| 67 | }; | ||
| 68 | |||
| 69 | /** | ||
| 70 | * vxfs_put_super - free superblock resources | ||
| 71 | * @sbp: VFS superblock. | ||
| 72 | * | ||
| 73 | * Description: | ||
| 74 | * vxfs_put_super frees all resources allocated for @sbp | ||
| 75 | * after the last instance of the filesystem is unmounted. | ||
| 76 | */ | ||
| 77 | |||
| 78 | static void | ||
| 79 | vxfs_put_super(struct super_block *sbp) | ||
| 80 | { | ||
| 81 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
| 82 | |||
| 83 | vxfs_put_fake_inode(infp->vsi_fship); | ||
| 84 | vxfs_put_fake_inode(infp->vsi_ilist); | ||
| 85 | vxfs_put_fake_inode(infp->vsi_stilist); | ||
| 86 | |||
| 87 | brelse(infp->vsi_bp); | ||
| 88 | kfree(infp); | ||
| 89 | } | ||
| 90 | |||
| 91 | /** | ||
| 92 | * vxfs_statfs - get filesystem information | ||
| 93 | * @sbp: VFS superblock | ||
| 94 | * @bufp: output buffer | ||
| 95 | * | ||
| 96 | * Description: | ||
| 97 | * vxfs_statfs fills the statfs buffer @bufp with information | ||
| 98 | * about the filesystem described by @sbp. | ||
| 99 | * | ||
| 100 | * Returns: | ||
| 101 | * Zero. | ||
| 102 | * | ||
| 103 | * Locking: | ||
| 104 | * No locks held. | ||
| 105 | * | ||
| 106 | * Notes: | ||
| 107 | * This is everything but complete... | ||
| 108 | */ | ||
| 109 | static int | ||
| 110 | vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp) | ||
| 111 | { | ||
| 112 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
| 113 | |||
| 114 | bufp->f_type = VXFS_SUPER_MAGIC; | ||
| 115 | bufp->f_bsize = sbp->s_blocksize; | ||
| 116 | bufp->f_blocks = infp->vsi_raw->vs_dsize; | ||
| 117 | bufp->f_bfree = infp->vsi_raw->vs_free; | ||
| 118 | bufp->f_bavail = 0; | ||
| 119 | bufp->f_files = 0; | ||
| 120 | bufp->f_ffree = infp->vsi_raw->vs_ifree; | ||
| 121 | bufp->f_namelen = VXFS_NAMELEN; | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int vxfs_remount(struct super_block *sb, int *flags, char *data) | ||
| 127 | { | ||
| 128 | *flags |= MS_RDONLY; | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * vxfs_read_super - read superblock into memory and initalize filesystem | ||
| 134 | * @sbp: VFS superblock (to fill) | ||
| 135 | * @dp: fs private mount data | ||
| 136 | * @silent: do not complain loudly when sth is wrong | ||
| 137 | * | ||
| 138 | * Description: | ||
| 139 | * We are called on the first mount of a filesystem to read the | ||
| 140 | * superblock into memory and do some basic setup. | ||
| 141 | * | ||
| 142 | * Returns: | ||
| 143 | * The superblock on success, else %NULL. | ||
| 144 | * | ||
| 145 | * Locking: | ||
| 146 | * We are under the bkl and @sbp->s_lock. | ||
| 147 | */ | ||
| 148 | static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) | ||
| 149 | { | ||
| 150 | struct vxfs_sb_info *infp; | ||
| 151 | struct vxfs_sb *rsbp; | ||
| 152 | struct buffer_head *bp = NULL; | ||
| 153 | u_long bsize; | ||
| 154 | struct inode *root; | ||
| 155 | |||
| 156 | sbp->s_flags |= MS_RDONLY; | ||
| 157 | |||
| 158 | infp = kmalloc(sizeof(*infp), GFP_KERNEL); | ||
| 159 | if (!infp) { | ||
| 160 | printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n"); | ||
| 161 | return -ENOMEM; | ||
| 162 | } | ||
| 163 | memset(infp, 0, sizeof(*infp)); | ||
| 164 | |||
| 165 | bsize = sb_min_blocksize(sbp, BLOCK_SIZE); | ||
| 166 | if (!bsize) { | ||
| 167 | printk(KERN_WARNING "vxfs: unable to set blocksize\n"); | ||
| 168 | goto out; | ||
| 169 | } | ||
| 170 | |||
| 171 | bp = sb_bread(sbp, 1); | ||
| 172 | if (!bp || !buffer_mapped(bp)) { | ||
| 173 | if (!silent) { | ||
| 174 | printk(KERN_WARNING | ||
| 175 | "vxfs: unable to read disk superblock\n"); | ||
| 176 | } | ||
| 177 | goto out; | ||
| 178 | } | ||
| 179 | |||
| 180 | rsbp = (struct vxfs_sb *)bp->b_data; | ||
| 181 | if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { | ||
| 182 | if (!silent) | ||
| 183 | printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); | ||
| 184 | goto out; | ||
| 185 | } | ||
| 186 | |||
| 187 | if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { | ||
| 188 | printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", | ||
| 189 | rsbp->vs_version); | ||
| 190 | goto out; | ||
| 191 | } | ||
| 192 | |||
| 193 | #ifdef DIAGNOSTIC | ||
| 194 | printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); | ||
| 195 | printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); | ||
| 196 | #endif | ||
| 197 | |||
| 198 | sbp->s_magic = rsbp->vs_magic; | ||
| 199 | sbp->s_fs_info = (void *)infp; | ||
| 200 | |||
| 201 | infp->vsi_raw = rsbp; | ||
| 202 | infp->vsi_bp = bp; | ||
| 203 | infp->vsi_oltext = rsbp->vs_oltext[0]; | ||
| 204 | infp->vsi_oltsize = rsbp->vs_oltsize; | ||
| 205 | |||
| 206 | if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) { | ||
| 207 | printk(KERN_WARNING "vxfs: unable to set final block size\n"); | ||
| 208 | goto out; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (vxfs_read_olt(sbp, bsize)) { | ||
| 212 | printk(KERN_WARNING "vxfs: unable to read olt\n"); | ||
| 213 | goto out; | ||
| 214 | } | ||
| 215 | |||
| 216 | if (vxfs_read_fshead(sbp)) { | ||
| 217 | printk(KERN_WARNING "vxfs: unable to read fshead\n"); | ||
| 218 | goto out; | ||
| 219 | } | ||
| 220 | |||
| 221 | sbp->s_op = &vxfs_super_ops; | ||
| 222 | root = iget(sbp, VXFS_ROOT_INO); | ||
| 223 | sbp->s_root = d_alloc_root(root); | ||
| 224 | if (!sbp->s_root) { | ||
| 225 | iput(root); | ||
| 226 | printk(KERN_WARNING "vxfs: unable to get root dentry.\n"); | ||
| 227 | goto out_free_ilist; | ||
| 228 | } | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | |||
| 232 | out_free_ilist: | ||
| 233 | vxfs_put_fake_inode(infp->vsi_fship); | ||
| 234 | vxfs_put_fake_inode(infp->vsi_ilist); | ||
| 235 | vxfs_put_fake_inode(infp->vsi_stilist); | ||
| 236 | out: | ||
| 237 | brelse(bp); | ||
| 238 | kfree(infp); | ||
| 239 | return -EINVAL; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* | ||
| 243 | * The usual module blurb. | ||
| 244 | */ | ||
| 245 | static struct super_block *vxfs_get_sb(struct file_system_type *fs_type, | ||
| 246 | int flags, const char *dev_name, void *data) | ||
| 247 | { | ||
| 248 | return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); | ||
| 249 | } | ||
| 250 | |||
| 251 | static struct file_system_type vxfs_fs_type = { | ||
| 252 | .owner = THIS_MODULE, | ||
| 253 | .name = "vxfs", | ||
| 254 | .get_sb = vxfs_get_sb, | ||
| 255 | .kill_sb = kill_block_super, | ||
| 256 | .fs_flags = FS_REQUIRES_DEV, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static int __init | ||
| 260 | vxfs_init(void) | ||
| 261 | { | ||
| 262 | vxfs_inode_cachep = kmem_cache_create("vxfs_inode", | ||
| 263 | sizeof(struct vxfs_inode_info), 0, | ||
| 264 | SLAB_RECLAIM_ACCOUNT, NULL, NULL); | ||
| 265 | if (vxfs_inode_cachep) | ||
| 266 | return (register_filesystem(&vxfs_fs_type)); | ||
| 267 | return -ENOMEM; | ||
| 268 | } | ||
| 269 | |||
| 270 | static void __exit | ||
| 271 | vxfs_cleanup(void) | ||
| 272 | { | ||
| 273 | unregister_filesystem(&vxfs_fs_type); | ||
| 274 | kmem_cache_destroy(vxfs_inode_cachep); | ||
| 275 | } | ||
| 276 | |||
| 277 | module_init(vxfs_init); | ||
| 278 | module_exit(vxfs_cleanup); | ||
