aboutsummaryrefslogtreecommitdiffstats
path: root/fs/freevxfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/freevxfs')
-rw-r--r--fs/freevxfs/Makefile8
-rw-r--r--fs/freevxfs/vxfs.h264
-rw-r--r--fs/freevxfs/vxfs_bmap.c280
-rw-r--r--fs/freevxfs/vxfs_dir.h92
-rw-r--r--fs/freevxfs/vxfs_extern.h76
-rw-r--r--fs/freevxfs/vxfs_fshead.c202
-rw-r--r--fs/freevxfs/vxfs_fshead.h67
-rw-r--r--fs/freevxfs/vxfs_immed.c114
-rw-r--r--fs/freevxfs/vxfs_inode.c351
-rw-r--r--fs/freevxfs/vxfs_inode.h180
-rw-r--r--fs/freevxfs/vxfs_kcompat.h49
-rw-r--r--fs/freevxfs/vxfs_lookup.c328
-rw-r--r--fs/freevxfs/vxfs_olt.c132
-rw-r--r--fs/freevxfs/vxfs_olt.h145
-rw-r--r--fs/freevxfs/vxfs_subr.c190
-rw-r--r--fs/freevxfs/vxfs_super.c278
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
5obj-$(CONFIG_VXFS_FS) += freevxfs.o
6
7freevxfs-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 */
46typedef int32_t vx_daddr_t;
47typedef 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 */
68struct 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 */
162struct 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 */
180enum 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 */
238enum {
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
42static void
43vxfs_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 */
65static daddr_t
66vxfs_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
103fail_size:
104 printk("vxfs: indirect extent to big!\n");
105fail_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 */
126static daddr_t
127vxfs_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
181fail:
182 pblock = 0;
183out:
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 */
199static daddr_t
200vxfs_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 */
258daddr_t
259vxfs_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
276unsupp:
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 */
50struct 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 */
65struct 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
41struct kmem_cache_s;
42struct super_block;
43struct vxfs_inode_info;
44struct inode;
45
46
47/* vxfs_bmap.c */
48extern daddr_t vxfs_bmap1(struct inode *, long);
49
50/* vxfs_fshead.c */
51extern int vxfs_read_fshead(struct super_block *);
52
53/* vxfs_inode.c */
54extern struct kmem_cache_s *vxfs_inode_cachep;
55extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
56extern struct inode * vxfs_get_fake_inode(struct super_block *,
57 struct vxfs_inode_info *);
58extern void vxfs_put_fake_inode(struct inode *);
59extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t);
60extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
61extern void vxfs_read_inode(struct inode *);
62extern void vxfs_clear_inode(struct inode *);
63
64/* vxfs_lookup.c */
65extern struct inode_operations vxfs_dir_inode_ops;
66extern struct file_operations vxfs_dir_operations;
67
68/* vxfs_olt.c */
69extern int vxfs_read_olt(struct super_block *, u_long);
70
71/* vxfs_subr.c */
72extern struct page * vxfs_get_page(struct address_space *, u_long);
73extern void vxfs_put_page(struct page *);
74extern 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
46static void
47vxfs_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 */
75static struct vxfs_fsh *
76vxfs_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 */
105int
106vxfs_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 */
44struct 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
41static int vxfs_immed_follow_link(struct dentry *, struct nameidata *);
42
43static 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 */
51struct 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 */
59struct 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 */
75static int
76vxfs_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 */
98static int
99vxfs_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
44extern struct address_space_operations vxfs_aops;
45extern struct address_space_operations vxfs_immed_aops;
46
47extern struct inode_operations vxfs_immed_symlink_iops;
48
49static 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
58kmem_cache_t *vxfs_inode_cachep;
59
60
61#ifdef DIAGNOSTIC
62/*
63 * Dump inode contents (partially).
64 */
65void
66vxfs_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 */
101struct vxfs_inode_info *
102vxfs_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
126fail:
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 */
143static 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
171fail:
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 */
187struct vxfs_inode_info *
188vxfs_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 */
201static __inline__ mode_t
202vxfs_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 */
233static void
234vxfs_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 */
269struct inode *
270vxfs_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 */
288void
289vxfs_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 */
302void
303vxfs_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 */
347void
348vxfs_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 */
58enum {
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 */
68struct vxfs_immed {
69 u_int8_t vi_immed[VXFS_NIMMED];
70};
71
72struct 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
82struct 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
88struct 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 */
99struct 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
10typedef long sector_t;
11
12/* From include/linux/fs.h (Linux 2.5.2-pre3) */
13static 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. */
19static 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) */
27static 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. */
40static 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
52static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
53static int vxfs_readdir(struct file *, void *, filldir_t);
54
55struct inode_operations vxfs_dir_inode_ops = {
56 .lookup = vxfs_lookup,
57};
58
59struct file_operations vxfs_dir_operations = {
60 .readdir = vxfs_readdir,
61};
62
63
64static __inline__ u_long
65dir_pages(struct inode *inode)
66{
67 return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
68}
69
70static __inline__ u_long
71dir_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 */
82static __inline__ int
83vxfs_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
92static __inline__ struct vxfs_direct *
93vxfs_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 */
112static struct vxfs_direct *
113vxfs_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 */
173static ino_t
174vxfs_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 */
204static struct dentry *
205vxfs_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 */
240static int
241vxfs_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
323done:
324 fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
325out:
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
41static __inline__ void
42vxfs_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
49static __inline__ void
50vxfs_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
57static __inline__ u_long
58vxfs_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 */
78int
79vxfs_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
129fail:
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 */
49enum {
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 */
65struct 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 */
83struct 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 */
91struct 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 */
99struct 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 */
108struct 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 */
118struct 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 */
130struct 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 */
139struct 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
43static int vxfs_readpage(struct file *, struct page *);
44static sector_t vxfs_bmap(struct address_space *, sector_t);
45
46struct address_space_operations vxfs_aops = {
47 .readpage = vxfs_readpage,
48 .bmap = vxfs_bmap,
49 .sync_page = block_sync_page,
50};
51
52inline void
53vxfs_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 */
70struct page *
71vxfs_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
91fail:
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 */
108struct buffer_head *
109vxfs_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 */
135static int
136vxfs_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 */
165static int
166vxfs_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 */
186static sector_t
187vxfs_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
50MODULE_AUTHOR("Christoph Hellwig");
51MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
52MODULE_LICENSE("Dual BSD/GPL");
53
54MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */
55
56
57static void vxfs_put_super(struct super_block *);
58static int vxfs_statfs(struct super_block *, struct kstatfs *);
59static int vxfs_remount(struct super_block *, int *, char *);
60
61static 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
78static void
79vxfs_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 */
109static int
110vxfs_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
126static 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 */
148static 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
232out_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);
236out:
237 brelse(bp);
238 kfree(infp);
239 return -EINVAL;
240}
241
242/*
243 * The usual module blurb.
244 */
245static 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
251static 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
259static int __init
260vxfs_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
270static void __exit
271vxfs_cleanup(void)
272{
273 unregister_filesystem(&vxfs_fs_type);
274 kmem_cache_destroy(vxfs_inode_cachep);
275}
276
277module_init(vxfs_init);
278module_exit(vxfs_cleanup);